Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
78.24% covered (success)
78.24%
2711 / 3465
64.29% covered (success)
64.29%
27 / 42
CRAP
0.00% covered (danger)
0.00%
0 / 1
AppController
78.24% covered (success)
78.24%
2711 / 3465
64.29% covered (success)
64.29%
27 / 42
13215.08
0.00% covered (danger)
0.00%
0 / 1
 beforeFilter
24.53% covered (danger)
24.53%
197 / 803
0.00% covered (danger)
0.00%
0 / 1
66437.52
 setLocalization
88.32% covered (success)
88.32%
121 / 137
0.00% covered (danger)
0.00%
0 / 1
130.63
 redirectUsingIpLang
45.00% covered (warning)
45.00%
9 / 20
0.00% covered (danger)
0.00%
0 / 1
11.99
 redirect
0.00% covered (danger)
0.00%
0 / 40
0.00% covered (danger)
0.00%
0 / 1
702
 setConfigLanguage
100.00% covered (success)
100.00%
27 / 27
100.00% covered (success)
100.00%
1 / 1
10
 jpyOnlyPage
100.00% covered (success)
100.00%
33 / 33
100.00% covered (success)
100.00%
1 / 1
13
 checkIfAllowed
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
1 / 1
6
 getTimezoneData
94.23% covered (success)
94.23%
49 / 52
0.00% covered (danger)
0.00%
0 / 1
15.04
 chargePayPalPaymentReceivable
94.02% covered (success)
94.02%
283 / 301
0.00% covered (danger)
0.00%
0 / 1
65.90
 chargePaymentReceivable
94.03% covered (success)
94.03%
63 / 67
0.00% covered (danger)
0.00%
0 / 1
14.04
 wpChargePaymentReceivable
96.63% covered (success)
96.63%
86 / 89
0.00% covered (danger)
0.00%
0 / 1
17
 setSeoLocalizeUrl
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
3
 getCustomCurrencyCode
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
5
 getPremiumPlanPrice
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
5
 checkStasapuDomain
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
5
 disablePageForSapuri
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
8
 blockWithdrawnSapuriToS
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
1 / 1
11
 createEnglishHubCookie
100.00% covered (success)
100.00%
19 / 19
100.00% covered (success)
100.00%
1 / 1
10
 checkControllerActionExist
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
5
 checkIfSNSShare
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
7
 setUpAppreciationSelectionModalElement
100.00% covered (success)
100.00%
56 / 56
100.00% covered (success)
100.00%
1 / 1
24
 sendTeacherAppreciation
100.00% covered (success)
100.00%
39 / 39
100.00% covered (success)
100.00%
1 / 1
14
 isLocalizeDirValid
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
 chargeAfteePaymentReceivable
96.13% covered (success)
96.13%
298 / 310
0.00% covered (danger)
0.00%
0 / 1
63
 checkAfteeSupported
100.00% covered (success)
100.00%
21 / 21
100.00% covered (success)
100.00%
1 / 1
25
 queryGuideControl
100.00% covered (success)
100.00%
54 / 54
100.00% covered (success)
100.00%
1 / 1
4
 queryLineHoverControl
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
1 / 1
3
 NCPlusPositionUrlScheme
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 checkLitePlanSupported
100.00% covered (success)
100.00%
35 / 35
100.00% covered (success)
100.00%
1 / 1
27
 resetPresetTextbook
100.00% covered (success)
100.00%
24 / 24
100.00% covered (success)
100.00%
1 / 1
4
 setPaypalUser
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
6
 checkStripeSupported
100.00% covered (success)
100.00%
32 / 32
100.00% covered (success)
100.00%
1 / 1
31
 processChildReceivablePayment
99.22% covered (success)
99.22%
127 / 128
0.00% covered (danger)
0.00%
0 / 1
20
 processChildPaypalPayment
96.49% covered (success)
96.49%
220 / 228
0.00% covered (danger)
0.00%
0 / 1
22
 processChildAfteePayment
96.43% covered (success)
96.43%
216 / 224
0.00% covered (danger)
0.00%
0 / 1
28
 processParentReceivablePayment
95.20% covered (success)
95.20%
119 / 125
0.00% covered (danger)
0.00%
0 / 1
19
 processParentPaypalPayment
95.54% covered (success)
95.54%
214 / 224
0.00% covered (danger)
0.00%
0 / 1
22
 savePaypalFailedSettlement
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
5
 processParentAfteePayment
96.40% covered (success)
96.40%
214 / 222
0.00% covered (danger)
0.00%
0 / 1
24
 checkCompanyIPForSMS
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
2
 setPerMonthSymbol
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
4
 corporateIpRestrictionLogout
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * Application level Controller
4 *
5 * This file is application-wide controller file. You can put all
6 * application-wide controller-related methods here.
7 *
8 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
9 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
10 *
11 * Licensed under The MIT License
12 * For full copyright and license information, please see the LICENSE.txt
13 * Redistributions of files must retain the above copyright notice.
14 *
15 * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
16 * @link          http://cakephp.org CakePHP(tm) Project
17 * @package       app.Controller
18 * @since         CakePHP(tm) v 0.2.9
19 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
20 */
21
22App::uses('Controller', 'Controller');
23
24/**
25 * Application Controller
26 *
27 * Add your application-wide methods in the class below, your controllers
28 * will inherit them.
29 *
30 * @package        app.Controller
31 * @link        http://book.cakephp.org/2.0/en/controllers.html#the-app-controller
32 */
33class AppController extends Controller {
34
35    /**
36     * セッションコンポーネント
37     *
38     * @var SessionComponent
39     */
40    var $Session;
41    public $uses = array(
42        'User',
43        'Notification',
44        'DefineMaster',
45        'CountryCode',
46        'LessonOnairsLog',
47        'LessonConnectionSpeedDetail',
48        'CountryCode',
49        'HeyNCUser',
50        'GuideNavigationbarCategory',
51        'GuideNavigationbarContent',
52        'GuideNavigationbarAuthControl',
53        'GuideNavigationbarMembershipControl',
54        'GuideNavigationbarCurrencyControl',
55        'GuideNavigationbarBrowserLangControl',
56        'CorporateActivationManagement',
57        'UsersDetail',
58        'CompCodeUsage',
59        'Corporate',
60        'RyugakuSchoolLineSetting',
61        'TeacherCoinBox',
62        'InhouseIp',
63        'Timezone'
64    );
65    public $helpers = array('Localize');
66    public $ext = '.php';
67    public $sharedUserData = false;
68    public $components = array(
69        'Paginator',
70        'RequestHandler',
71        'DebugKit.Toolbar',
72        'Session',
73        'Cookie',
74        'Auth' => array(
75            'authenticate'=>array(
76                'Form'=>array(
77                    'fields'=>array('username'=>'email','password'=>'password')
78                )
79            ),
80            'loginRedirect' => array('controller' => 'home', 'action' => 'index'),
81            'logoutRedirect' => array('controller' => 'login', 'action' => 'index'),
82            'loginAction' => '/login',
83            'authError' => '再度ログインしなおしてください。',
84            'loginError' => 'メールアドレス、またはパスワードに誤りがあります。'
85        )
86    );
87    public $slackChannel = "";
88    public $mySlack = NULL;
89    private $a8Url = ""; 
90    private $affiliateUrl = ""; // Affiliate url callback
91    public $timeDiff = 0; // default
92    public $timeDiffSecond = 0;
93    public $displayTime = 0;
94    public $utcOffset = "09:00";// default tokyo
95    public $lang_iso = "";
96    public $parentId = NULL;
97    public $localizeDir;
98    public $baseUrl;
99    public $clpip; // NC-7360 : corporate light plan individual payment
100    public $allowedCoupon = false; 
101    public $studySapuriId = NULL; // NC-7922, Stasap toC/toB(old)
102    public $allowedCurrencies;
103    public $isPayPalUser = false;
104    public $isAfteeUser = false;
105    public $mobAppUserData;
106    public $isSNSShare;
107    public $isSNSShareOverseas;
108    public $studentLessonPriorityTimeDelayInSeconds = 0;
109    public $isStudySapuriTosUser = false; # -stasap toS(new) members, flagging
110    public $isStudySapuriUser = false; # -either Stasap toC/toB/toS(new) members, flagging
111    public $isTemporaryPassword = false;
112    public $localizeIPLang;
113    public $isIndividualCorp = false;
114    public $corpStandardPremiumPaymentPlans = [];
115    public $isStripeUser = false;
116    public $isStripeAppleUser = false;
117    public $isStripeGoogleUser = false;
118    public $isSetLineHoverSetting = false;
119    public $userMembershipType = null;
120    public $isWithdrawn = false;
121
122    public function beforeFilter() {
123        $this->Cookie->httpOnly = true;
124
125        /*Configure Path*/
126        App::build(array(
127            'Model'=>array(
128                ROOT.'/lib/Model/Base/',
129                ROOT.'/lib/Model/',
130                ROOT.'/lib/Model/',
131                ROOT.'/lib/Model/Form/'),
132            'Lib'=>array(
133                ROOT.'/lib/Lib/'
134            ),
135            'Vendor'=>array(
136                ROOT.'/lib/Vendor/'
137            )
138        ));
139        
140        /*Autoload Model*/
141        App::import('Model',array('CommonTable'));
142        App::import('Model',array('CourseMaster'));
143        App::import('Model',array('DefineMaster'));
144
145        /*Autoload Lib*/
146        App::uses('myTools','Lib');
147        App::uses('myMailer','Lib');
148        App::uses('myError','Lib');
149        App::uses('myTranslator','Lib');
150        App::uses('myMemcached', 'Lib');
151        App::uses('textbookTemplate', 'Lib');
152        App::uses('mySlack','Lib');
153        App::uses('wpPaymentService','Lib');
154        App::uses('CommonCache','Lib');
155        App::uses('OfficeAccounting','Lib');
156        App::uses('LineMessageBot', 'Lib'); // NJ-37740
157
158        /*Autoload table class*/
159        spl_autoload_register(function($class){
160            $classFile1 = ROOT.'/lib/Model/'.$class.'.php';
161            $classFile2 = ROOT.'/lib/Model/Form/'.$class.'.php';
162            if(is_file($classFile1)){ require_once($classFile1); }
163            if(is_file($classFile2)){ require_once($classFile2); }
164        });
165
166        //*NC-4284: if url has user remove user and redirect
167        $webUrl = $_SERVER['REQUEST_URI'];
168        $this->parseUrl = parse_url($webUrl);
169        $segment = explode('/', $webUrl);
170        $firstSegment = isset($segment[1])? $segment[1]:'';
171        $secondSegment = isset($segment[2])? $segment[2]:'';
172
173        if (!$this->request->is('post') && !$this->request->is('ajax')) {
174            if ($this->Auth->loggedIn()) {
175                // if (!$this->RequestHandler->isMobile() && !$this->isLocalizeDirValid($this->Cookie->read('localizeDir'))) {
176                //     $this->Session->destroy();
177                //     $past = time() - 3600;
178                //     foreach ( $_COOKIE as $key => $value )
179                //     {    
180                //         setcookie( $key, $value, $past, '/' );
181                //     }
182                // }
183            }
184
185            if ($firstSegment == 'user') {
186                # added localize URL
187                if($secondSegment == 'ja') {
188                    $getNewUrl = str_replace("/user/ja/", "", $webUrl);
189                } else {
190                    $getNewUrl = str_replace("/user/", "", $webUrl);
191                }
192                $url = myTools::getUrl() ."/". $getNewUrl;
193
194                $this->log("Redirect : " . $url , "debug");
195                return $this->redirect($url, 301);
196            }
197
198            # added localize URL
199            if ($firstSegment == 'ja') {
200                if ($webUrl == "/ja" && $segment[2] == '') {
201                    $url = myTools::getUrl();
202                } else {
203                    $getNewUrl = str_replace("/ja/", "", $webUrl);
204                    $url = myTools::getUrl() ."/". $getNewUrl;
205                }
206
207                $this->log("Redirect : " . $url , "debug");
208                return $this->redirect($url, 301);
209            }
210        }
211
212        /*Autoload table class*/
213        spl_autoload_register(function($class){
214            $classFile1 = ROOT.'/lib/Model/'.$class.'.php';
215            $classFile2 = ROOT.'/lib/Model/Form/'.$class.'.php';
216            if(is_file($classFile1)){ require_once($classFile1); }
217            if(is_file($classFile2)){ require_once($classFile2); }
218        });
219        
220        // - if maintenance check
221        if (strtolower(trim($this->request->params['controller'])) == "maintenance-check.html") {
222            return false;
223        }
224        
225        //set language to null to avoid overwriting
226        Configure::write('Config.language', NULL);
227
228        /*Autoload Lib*/
229        Configure::load('my');
230        Configure::load('const');
231
232        if($this->Auth->loggedIn()){
233            $user = $this->Auth->user();
234            $localLang = isset($this->request->data['localizeDir']) ? $this->request->data('localizeDir') : $firstSegment;
235            $params = array(
236                'currency_code' => $user['currency_code'] ?? null,
237                'created' => $user['created'] ?? null,
238                'language' => $localLang
239            );
240
241            if($this->User->languageAccessControlCheck($params) && (!in_array($firstSegment, ['access_control', 'login', 'logout']) && !in_array($secondSegment, ['access_control', 'login', 'logout']))){
242                if(in_array($firstSegment, ['zh-tw', 'zh-cn', 'vi'])){
243                    $latestUrl = preg_replace('/\/(zh-tw|zh-cn|vi)\//', '/', $webUrl);
244                    if(!empty($secondSegment)) {
245                        $this->Session->write("latestAccessUrl" , $latestUrl);
246                    } else {
247                        $this->Session->write("latestAccessUrl" , '/');
248                    }
249                }
250                $url = myTools::getUrl() . "/access_control";
251                return $this->redirect($url, 302);
252            }
253        }
254
255        // - memcache declaration
256        $memcached = new myMemcached();
257        
258        //remove trailing slashes only if not post and not ajax
259        if (!$this->request->is('post') && !$this->request->is('ajax')) {
260            $currURLSTR = $this->here;
261            if (substr($currURLSTR, -1) == '/' && $currURLSTR != '/user/') {
262
263                $currURLSTR = rtrim($currURLSTR, '/');
264                //check if theres a GET data to be append
265                if (!empty($_SERVER['QUERY_STRING'])) {
266                    $currURLSTR = $currURLSTR . '?' . $_SERVER['QUERY_STRING'];
267                }
268
269                // if (!$this->RequestHandler->isMobile() && !$this->isLocalizeDirValid($this->Cookie->read('localizeDir'))) {
270                //     $this->log("redirect_debug -> invalid localizeDirectory" . json_encode($this->Cookie->read('localizeDir')) , "debug");
271                //     return $this->redirect('/');
272                // }
273                
274                return $this->redirect(myTools::getUrl() . $currURLSTR, 301);
275            }
276        }
277
278        if(isset($this->params->params['controller']) &&
279            in_array($this->params->params['controller'], array('register', 'spRegister', 'forgot', 'sp')) &&
280            isset($this->params->params['action']) &&
281            in_array($this->params->params['action'], array('activate_email', 'activate', 'forgotactivate')) &&
282            isset($this->params->params['code'])
283        ) {
284
285            if($this->RequestHandler->isMobile() == false && $this->params->params['controller'] == 'spRegister' && $this->params->params['action'] === 'activate') {
286                return $this->redirect('/register/activate-email/' . $this->params->params['code']);
287            }
288        }
289
290        $paymentPlans = Configure::read('payment_plans');
291        $this->corpStandardPremiumPaymentPlans = [
292            $paymentPlans['corporate_standard_plan'],
293            $paymentPlans['corporate_standard_card_plan'],
294            $paymentPlans['corporate_standard_individual_plan'],
295            $paymentPlans['corporate_premium_plan'],
296            $paymentPlans['corporate_premium_card_plan'],
297            $paymentPlans['corporate_premium_individual_plan']
298        ];
299        $this->set('corpStandardPremiumPaymentPlans', $this->corpStandardPremiumPaymentPlans);
300        $this->set('userCDNPath', Configure::read('user.cdn_path_webroot'));
301        $this->set('userCDNPathV2', Configure::read('user.cdn_path_webroot_v2'));
302        
303        /*Security Check*/
304        $user = $this->Auth->user();
305
306        $skipBeforeFilterActions = Configure::read('skipped_actions_before_filter');  // NJ-47850: Define the actions to skip the beforeFilter
307        // NJ-47850: Get the current controller and action
308        $currentController = $this->name;
309        $currentAction = $this->action;
310        
311        // Check if the current action should skip the beforeFilter
312        if (isset($skipBeforeFilterActions[$currentController]) && in_array($currentAction, $skipBeforeFilterActions[$currentController])) {
313            $datetime = time();
314            
315            if(isset($user) && !empty($user['id'])){
316                $memcachedTimeDiff = $memcached->get('user-timediff-' . $user['id']);
317
318                if (isset($memcachedTimeDiff['timeDiff']) || isset($memcachedTimeDiff['utc'])) {
319                    $this->timeDiff = isset($memcachedTimeDiff['timeDiff']) && is_numeric($memcachedTimeDiff['timeDiff']) ? $memcachedTimeDiff['timeDiff'] : 0;
320                    $this->utcOffset = $memcachedTimeDiff['utc'];
321                    $this->displayTime = $this->Timezone->getUserTime(array('timeDiff' => $this->timeDiff));
322                }else{
323                    $this->displayTime = $datetime;
324                }
325            }else{
326                $this->displayTime = $datetime;
327            }
328            
329            return false;
330        }
331        // end NJ-47850
332        
333        /*meta title*/
334        $meta = Configure::read('my.meta.'.strtolower($this->name));
335        if (!$meta) {
336            $meta = Configure::read('my.meta.'.strtolower($this->action));
337        }
338        if (!$meta) {
339            $meta = Configure::read('my.meta.'.strtolower($this->name).'-'.strtolower($this->action));
340        }
341        if (!empty($meta['title'])) {
342            $this->set('title_for_layout',$meta['title']);
343        }
344        if (!empty($meta['keywords'])) {
345            $this->set('meta_keywords',$meta['keywords']);
346        }
347        if (!empty($meta['description'])) {
348            $this->set('meta_description',$meta['description']);
349        }
350
351        if (!$this->Auth->loggedIn() && $this->Cookie->read('rememberMe') && !$this->RequestHandler->isMobile()) {
352            $cookie = $this->Cookie->read('rememberMe');
353            $this->User->openDBReplica();
354            $this->User->recursive = -1;
355            $data = $this->User->findByEmailAndPassword(myTools::decode($cookie['ae']),myTools::decode($cookie['ap']));
356            $this->User->closeDBReplica();
357            if ($data) {
358                $this->Auth->login($data['User']);
359                if (!$this->RequestHandler->isMobile()) {
360                    return $this->redirect(myTools::getUrl() . '/user/mypage');
361                }
362            }
363        }
364
365        $hideA8 = false;
366        $hideEngHub = false;
367        $engHubCookieIndexStr = null;
368        if (!$this->Auth->loggedIn()) {
369            $cookieTime = Configure::read("cookieTime");            
370            if (isset($this->request->query['cc']) && $this->request->query['cc'] != '') {
371                //extract prefix from cc
372                $cc = explode('_', $this->request->query['cc']);
373                $prefix = isset($cc[0]) ? trim(strtolower($cc[0])) : false;
374                if ($prefix == 'fr') {
375                    // NJ-6146 Check campaign code is FR -> auto redirect to FR_CP
376                    if (isset($cc[1]) && strtolower($cc[1]) != 'cp') {
377                        $query = $this->request->query;
378                        $cc[0] = 'FR_CP';
379                        $query['cc'] = implode('_', $cc);
380                        $query_string = http_build_query($query);
381
382                        $url = $this->here . '?' . $query_string;
383
384                        // $this->log("Redirect : " . $url , "debug");
385
386                        return $this->redirect(myTools::getUrl() . $url, 301);
387                    }
388                    // log
389                    $this->log("[REFERRAL] saving referral code '".$this->request->query['cc']."'' to Cookie! ", "debug");    
390                }
391                
392                $this->Cookie->write('campaign_code', $this->request->query['cc'], true, $cookieTime);
393            }
394            
395            //save cookie a8 identification
396            if (isset($this->request->query['a8']) && !empty($this->request->query['a8'])) {
397                $this->Cookie->write('a8_id', $this->request->query['a8'], true, $cookieTime);
398            }
399
400            // NC-8916 - Generate english hub cookie
401            $engHubCookieIndexStr = $this->createEnglishHubCookie();
402
403            // NJ-26035 - save cookie for google cloud id 
404            if (
405                (isset($this->request->query['gclid']) && !empty($this->request->query['gclid']))
406            ) {
407            
408                $googleCloudCookie = $this->Cookie->read('gclid');
409
410                // - save the cookie if not yet saved
411                if (!$googleCloudCookie) {
412                    $this->Cookie->write('gclid', $this->request->query['gclid'], true, $cookieTime);
413                }
414
415                // - save the cookie when the saved cookie is not the same as the params google cloud id
416                if (
417                    $googleCloudCookie && 
418                    $googleCloudCookie != $this->request->query['gclid']
419                ) {
420                    $this->Cookie->write('gclid', $this->request->query['gclid'], true, $cookieTime);
421                }
422            }
423
424            //NJ-63077 - save cookie for facebook cloud id and tiktok cloud id
425            if (
426                (isset($this->request->query['fbclid']) && !empty($this->request->query['fbclid'])) || (isset($this->request->query['ttclid']) && !empty($this->request->query['ttclid']))
427            ) {
428            
429                $facebookCloudCookie = $this->Cookie->read('fbclid');
430                $tiktokCloudCookie = $this->Cookie->read('ttclid');
431
432                // - save the cookie if not yet saved
433                if (!$facebookCloudCookie) {
434                    $this->Cookie->write('fbclid', $this->request->query['fbclid'], true, $cookieTime);
435                }
436                
437                if (!$tiktokCloudCookie) {
438                    $this->Cookie->write('ttclid', $this->request->query['ttclid'], true, $cookieTime);
439                }
440
441                // - save the cookie when the saved cookie is not the same as the params google cloud id
442                if (
443                    $facebookCloudCookie && 
444                    $facebookCloudCookie != $this->request->query['fbclid']
445                ) {
446                    $this->Cookie->write('fbclid', $this->request->query['fbclid'], true, $cookieTime);
447                }
448
449                if (
450                    $tiktokCloudCookie && 
451                    $tiktokCloudCookie != $this->request->query['ttclid']
452                ) {
453                    $this->Cookie->write('ttclid', $this->request->query['ttclid'], true, $cookieTime);
454                }
455            }
456            
457            //NJ-63077 - delete other cloud id cookies if one is set
458            if (!empty($this->request->query['gclid'])) {
459                $this->Cookie->delete('fbclid');
460                $this->Cookie->delete('ttclid');
461            } elseif (!empty($this->request->query['fbclid'])) {
462                $this->Cookie->delete('gclid');
463                $this->Cookie->delete('ttclid');
464            } elseif (!empty($this->request->query['ttclid'])) {
465                $this->Cookie->delete('gclid');
466                $this->Cookie->delete('fbclid');
467            }
468
469        } else {
470            //check if complimentary user
471            $complimentary_code = $this->Auth->user('complimentary_code');
472            if (!empty($complimentary_code)) {
473                $hideA8 = true;
474                $hideEngHub = true;
475            }
476        }
477
478        //check a8 exist
479        if ($this->Cookie->check('a8_id') && !$hideA8) {
480            $encodeURL = myTools::getUrl() . '/api/users/purchase_done?a8=' . $this->Cookie->read('a8_id') . '&api_token={partner_parameters}';
481            $this->a8Url = 'event_callback_a967je=' . urlencode($encodeURL);
482            $this->affiliateUrl = $this->a8Url;
483        }
484
485
486        // NC-8916 : check english hub affiliate tracking
487        $ehubCookieIndex = Configure::read('english_hub_affiliate_param.p');
488        if ( $this->Cookie->check($engHubCookieIndexStr) && !$hideEngHub ) {
489            $setcid = $this->Cookie->read($engHubCookieIndexStr);
490            $encodeURL = myTools::getUrl() . '/api/users/purchase_done?cid=' . $setcid . '&api_token={partner_parameters}';
491            $this->affiliateUrl = 'event_callback_a967je=' . urlencode($encodeURL);
492        }
493
494        $this->set('affiliateUrl', $this->affiliateUrl);
495        $this->set('a8Url', $this->a8Url);
496        $this->set('a8_id', $this->Cookie->read('a8_id'));
497
498        //if cookie is not set then detect device then set cookie
499        if(!isset($_COOKIE['viewMode'])) {
500            $device = myTools::getDevice();
501            if ($device == 2 || $device == 3 || $device == 4) {
502                setcookie('viewMode', 'sp', 0, '/');
503            } else {
504                setcookie('viewMode', 'pc', 0, '/');
505            }
506        }
507
508        //NC-4772 [Asia deployment] [Mobapp] 
509        $parentData = $this->User->setConfigLanguage($this->request->query);
510        $this->set('current_lang', $parentData['current_lang']);
511        $this->set('restriction', $parentData['restriction']);
512
513        $this->set('ver', Configure::read('user.version'));
514
515        //get parent_id for family validation
516        $this->parentId = isset($parentData['User']['parent_id']) ? $parentData['User']['parent_id'] : NULL;
517
518        // check if from SNS share        
519        $this->isSNSShare = $this->checkIfSNSShare();
520        $this->isSNSShareOverseas = (isset($_GET["nc_sns_is_overseas"]) && $_GET["nc_sns_is_overseas"] == 1) ? true : false;
521        $this->set('isSNSShare', $this->isSNSShare);
522
523        # NC-7196: LOCALIZE URL
524        $this->localizeDir = Configure::read('default.localization');
525        $this->setLocalization();
526        $this->setSeoLocalizeUrl();
527
528        # NJ-18262 : Guide Control
529        $redis = new myRedis();
530        $guideControlCached = $redis->get("dynamic_global_guide_control");
531        $lineGuideControlCached = $redis->get("dynamic_line_hover_guide_control");
532
533        if (!$guideControlCached){
534            $this->queryGuideControl();
535        } else {
536            $guideNavigationbarCategory = json_decode($redis->get("dynamic_global_guide_control"),true);
537            $this->set('GuideNavigationbarCategory', $guideNavigationbarCategory);
538        }
539
540        if (!$this->isSetLineHoverSetting) {
541            $this->isSetLineHoverSetting = true;
542            $this->queryLineHoverControl();
543        }
544
545        // check if url is from payment kickback "bypass maintenance redirection for zeus and worldpay"
546        $isPayment = in_array(strtolower($this->params['action']), ['zeuspay', 'getwppaymentresult', 'getafteepaymentresult','school_zeuspay','school_zeuspay_bank', 'stripepay', 'stripepay_manual']);
547
548        // - check if maintenance
549        if (!myTools::checkCompanyIP($_SERVER['REMOTE_ADDR']) && !$isPayment) {
550            $maintenance = MaintenanceTable::getMaintenance();
551            if ($maintenance) {
552                // CHECK IF ACCESS TYPE NOT SEO CRAWLER
553                if ( myTools::isCrawler() === FALSE ) {
554                    $controller = strtolower($this->params['controller']);
555                    $action = strtolower($this->params['action']);
556                    if ( $this->Auth->loggedIn() ) {
557                        $this->log('[NJ-65075] AppController.php L#'.__LINE__.' -- '.json_encode(array('request_data' => $this->request, 'user_agent' => $_SERVER['HTTP_USER_AGENT'])), 'error');
558                        $this->Auth->logout();
559                    }
560
561                    if($controller != 'maintenance' && !in_array($action, array('regular', 'checkmaintenance'))) {
562                        if (
563                            strpos($_SERVER['REQUEST_URI'], "/ko") !== false ||
564                            strpos($_SERVER['REQUEST_URI'], "/zh-tw")  !== false ||
565                            strpos($_SERVER['REQUEST_URI'], "/vi")  !== false
566                        ) {
567                            return $this->redirect('/../maintenance/regular');
568                        }
569                        return $this->redirect('/maintenance/regular');
570                    }
571                }
572            }
573        }
574        
575        //add link to sp
576        $device = myTools::getDevice();
577        $showLink = ($device == 2 || $device == 3 || $device == 4)? 1: 0;
578        $this->set('showLink', $showLink);
579        
580        // check current controller
581        $currentPageController = isset($this->params['controller']) ? trim(strtolower($this->params['controller'])) : null;
582        $userData = false;
583        
584        // if logged in
585        if ($this->Auth->loggedIn()) {
586            # get user data
587            $this->User->openDBReplica();
588            $this->User->virtualFields['complimentary_code'] = "(SELECT Code.code FROM comp_code_usage AS Code WHERE Code.user_id = User.id AND Code.active_flg = 1 LIMIT 1)";
589            $userData = $this->User->find('first', array(
590                'fields' => [
591                    'User.*',
592                    'UsersExtend.*',
593                    'UsersDetail.*',
594                    'CorporateActivationManagement.*'
595                ],
596                'joins' => [
597                    [
598                        'table' => 'users_extend',
599                        'alias' => 'UsersExtend',
600                        'type' => 'LEFT',
601                        'conditions' => 'UsersExtend.user_id = User.id'
602                    ],
603                    [
604                        'table' => 'corporate_activation_managements',
605                        'alias' => 'CorporateActivationManagement',
606                        'type'    => 'LEFT',
607                        'conditions'    => 'User.id = CorporateActivationManagement.user_id'
608                    ],
609                    [
610                        'table' => 'users_detail',
611                        'alias' => 'UsersDetail',
612                        'type' => 'LEFT',
613                        'conditions' => 'UsersDetail.user_id = User.id'
614                    ]
615                ],
616                'recursive' => -1,
617                'conditions' => array('User.id' => $this->Auth->user('id'))
618            ));
619            $this->User->closeDBReplica();
620
621            $userData['User']['payment_plan_id'] ??= '';
622            $userData['User']['corporate_id'] ??= '';
623            $userData['User']['corporate_individual_payment_flg'] ??= '';
624
625            $this->isWithdrawn = (isset($userData['User']['status']) && $userData['User']['status'] == 9) ? true : false;
626            
627            // redirect to change pass if stasapu tos user and temporary password not change.
628            if (
629                !$this->RequestHandler->isMobile() &&
630                strtolower($this->params->params['action']) != 'changefirstpass' &&
631                strtolower($this->params->params['action']) != 'logout' &&
632                isset($userData['UsersExtend']['temporary_pw_flg']) &&
633                $userData['UsersExtend']['temporary_pw_flg']
634            ) {
635                return $this->redirect('/account/change-first-pass');
636            } elseif(
637                // NJ-23929: redirect to change pass if user is registered through corporate
638                !$this->RequestHandler->isMobile() &&
639                strtolower($this->params->params['action']) != 'changefirstpass' &&
640                strtolower($this->params->params['action']) != 'logout' &&
641                isset($userData['CorporateActivationManagement']['temporary_pw_flg']) &&
642                $userData['CorporateActivationManagement']['temporary_pw_flg'] == 1
643            ){
644                return $this->redirect('/account/change-first-pass');
645            } elseif (
646                $this->RequestHandler->isMobile() &&
647                strtolower($this->params->params['controller']) != 'account' &&
648                strtolower($this->params->params['controller']) != 'index' &&
649                strtolower($this->params->params['action']) != 'logout' &&
650                isset($userData['UsersExtend']['temporary_pw_flg']) &&
651                $userData['UsersExtend']['temporary_pw_flg']
652            ) {
653                return $this->redirect('/account');
654            }
655
656            $userObj = new UserTable($userData['User']);
657            $userObj->currency_code ??= '';
658            if ($this->request->params['controller'] === 'login' &&
659                ($this->request->params['action'] === 'index' || $this->request->params['action'] === 'logout')) {
660                return;
661            }
662
663            if (!$this->RequestHandler->isMobile() && in_array($userObj->corporate_id, Configure::read("blocked_corporate_member_types"))) {
664                $remoteAddress = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : "0.0.0.0";
665
666                if (!in_array($remoteAddress, Configure::read("corporate_allowed_ip"))) {
667
668                    $params = array(
669                        'message' => '特定法人で許可されていないIPアドレスからアクセスがありました。',
670                        'member_id' => $user['id'],
671                        'type' => 'IPアドレス:' . $remoteAddress,
672                    );
673
674                    $userObj->slackSoftbankNotice($params);
675
676                    return $this->corporateIpRestrictionLogout();
677                }
678            }
679
680            $this->allowedCoupon = $userObj->allowedMemberCoupon();
681
682            #NC-7922: update username fo studysapuri
683            if (isset($userData['User']['studysapuri_id']) && $userData['User']['studysapuri_id']) {
684                $userData['User']['nickname'] = str_replace("[Study Sapuri ENGLISH] ","", $userData['User']['nickname']);
685            }
686
687            if (
688                isset($userData['User']['card_company']) &&
689                (
690                    $userData['User']['card_company'] == Configure::read('card_company.paypal') ||
691                    isset($userData['User']['paypal_billing_agreement_id'])
692                )
693            ) {
694                $this->isPayPalUser = true;
695            } else if (
696                isset($userData['User']['card_company']) &&
697                (
698                    $userData['User']['card_company'] == Configure::read('card_company.aftee') || 
699                    (empty($userData['User']['card_company']) && $userData['User']['card_brand'] == 'AFTEE' && !empty($userData['User']['aftee_transaction_identifier']))
700                )
701            ) {
702                $this->isAfteeUser = true;
703            } else if (
704                in_array($userData['User']['card_company'], Configure::read('card_company.stripe')) || 
705                (!empty($userData['User']['stripe_customer_id']) && !empty($userData['User']['stripe_payment_identifier']))
706            ) {
707                $this->isStripeUser = true;
708
709                if ($userData['User']['card_company'] == Configure::read('card_company.stripe.apple')) {
710                    $this->isStripeAppleUser = true;
711                } elseif ($userData['User']['card_company'] == Configure::read('card_company.stripe.google')) {
712                    $this->isStripeGoogleUser = true;
713                }                
714            }
715
716            if (!empty($userData['User']['timezone_id'])) {
717                $this->loadModel('Timezone');
718                //get memcached timezone
719                $memcachedTimeDiff = $memcached->get('user-timediff-' . $userData['User']['id']);
720                if (!isset($memcachedTimeDiff['timeDiff']) || !isset($timeDiffData['utc'])) {
721                    $this->Timezone->openDBReplica();
722                    $timezone = $this->Timezone->find('first', array(
723                        'fields' => array('Timezone.continent_id', 'Timezone.city_eng'),
724                        'conditions' => array('Timezone.id' => $userData['User']['timezone_id'])
725                    ));
726                    $this->Timezone->closeDBReplica();
727                    $timeDiffData = array('success' => false);
728                    if ($timezone) {
729                        //get user time difference
730                        $timeDiffData = $this->Timezone->computeTimeDiff(array('continent_id' => $timezone['Timezone']['continent_id'], 'city' => $timezone['Timezone']['city_eng']));
731                    }
732                    if ($timeDiffData['success']) {
733                        $this->timeDiff = $timeDiffData['timeDiff'];
734                        $this->utcOffset = $timeDiffData['utc'];
735                     }
736
737                    //save to memcache
738                    $memcached->set(array(
739                        'key' => 'user-timediff-' . $userData['User']['id'],
740                        'value' => array(
741                            'timeDiff' => $this->timeDiff,
742                            'utc' => $this->utcOffset
743                        ),
744                        'expire' => 604800 //1 week
745                     ));
746                } else {
747                    //get memcached time difference
748                    $this->timeDiff = $memcachedTimeDiff['timeDiff'];
749                    $this->utcOffset = $memcachedTimeDiff['utc'];
750                }
751                //compute time difference in seconds
752                $this->timeDiffSecond = intval($this->timeDiff * 60);
753                //get user time
754                $this->displayTime = $this->Timezone->getUserTime(array('timeDiff' => $this->timeDiff));
755            } else {
756                //use server timezone Asia/Tokyo if timezone is not set
757                $this->displayTime = time();
758            }
759
760            // NC-7360 : Corporate Light Individual Payment
761            $corpType = myTools::getCoporateTypeUsingPaymentPlanId($userData['User']['payment_plan_id'] );
762            $this->clpip = ($userData['User']['corporate_id'] && $corpType == Configure::read("corporate_type.light") && $userData['User']['corporate_individual_payment_flg'] == 1);
763
764            // NC-7922
765            $this->studySapuriId = isset($userData['User']['studysapuri_id']) ? $userData['User']['studysapuri_id'] : NULL;
766            $this->isStudySapuriTosUser = !empty($userData['UsersExtend']['id']) ? true : false;
767            $this->isTemporaryPassword = $userData['UsersExtend']['temporary_pw_flg'] ?? '';
768            $this->defaultCameraSetting = (isset($userData['UsersDetail']['new_camera_flg']) && is_numeric($userData['UsersDetail']['new_camera_flg'])) ? $userData['UsersDetail']['new_camera_flg'] : 1;
769        } else {
770            //use system time if not yet login
771            $this->displayTime = time();
772
773            $apiToken = isset($this->request->query['token']) ? $this->request->query['token'] : null;
774            if (trim($apiToken) != null) {
775                $this->User->openDBReplica();
776                $appUserData = $this->User->find('first', array(
777                    'fields' => array(
778                        'User.id',
779                        'User.currency_code',
780                        'User.studysapuri_id',
781                        'User.corporate_id',
782                        'User.card_company',
783                        'User.paypal_billing_agreement_id',
784                        'UsersExtend.id',
785                        'User.aftee_transaction_identifier',
786                        'User.card_brand',
787                        'User.card_number',
788                        'User.paypal_payer_id',
789                        'User.paypal_payer_email',
790                        'User.stripe_customer_id',
791                        'User.stripe_payment_identifier',
792                        'User.payment_plan_id',
793                        'User.status',
794                    ),
795                    'joins' => [
796                        [
797                            'table' => 'users_extend',
798                            'alias' => 'UsersExtend',
799                            'type' => 'LEFT',
800                            'conditions' => 'UsersExtend.user_id = User.id'
801                        ]
802                    ],
803                    'conditions' => array('User.api_token' => $this->request->query['token']),
804                    'recursive' => -1,
805                ));
806                $this->User->closeDBReplica();
807
808                if ($appUserData) {
809                    // set sapuri id
810                    if (isset($appUserData['User']['studysapuri_id'])) {
811                        $this->studySapuriId = $appUserData['User']['studysapuri_id'];
812                    }
813
814                    if (!empty($appUserData['UsersExtend']['id'])) {
815                        $this->isStudySapuriTosUser = true;
816                    }
817
818                    // set isPayPalUser
819                    if (
820                        (isset($appUserData['User']['card_company']) && $appUserData['User']['card_company'] == Configure::read('card_company.paypal')) ||
821                        isset($appUserData['User']['paypal_billing_agreement_id'])
822                    ) {
823                        $this->isPayPalUser = true;
824                    }
825
826                    // set isAfteeUser
827                    if (
828                        (isset($appUserData['User']['card_company']) && $appUserData['User']['card_company'] == Configure::read('card_company.aftee')) ||
829                        (empty(isset($appUserData['User']['card_company'])) && isset($appUserData['User']['card_brand']) && isset($appUserData['User']['aftee_transaction_identifier']) && $appUserData['User']['card_brand'] == 'AFTEE' && !empty($appUserData['User']['aftee_transaction_identifier']))
830                    ) {
831                        $this->isAfteeUser = true;
832                    }
833
834                    // set isStripeUser 
835                    if (
836                        (isset($appUserData['User']['card_company']) && in_array($appUserData['User']['card_company'], Configure::read('card_company.stripe'))) || 
837                        (empty($appUserData['User']['card_company']) && isset($appUserData['User']['stripe_customer_id']) && isset($appUserData['User']['stripe_payment_identifier']) && !empty($appUserData['User']['stripe_customer_id']) && !empty($appUserData['User']['stripe_payment_identifier']))
838                    ) {
839                        $this->isStripeUser = true;
840                    
841                        if (isset($appUserData['User']['card_company'])) {
842                            if ($appUserData['User']['card_company'] == Configure::read('card_company.stripe.apple')) {
843                                $this->isStripeAppleUser = true;
844                            } elseif ($appUserData['User']['card_company'] == Configure::read('card_company.stripe.google')) {
845                                $this->isStripeGoogleUser = true;
846                            }
847                        }
848                    }
849
850                    $this->isWithdrawn = (isset($appUserData['User']['status']) && $appUserData['User']['status'] == 9) ? true : false;
851
852                    $this->mobAppUserData = $appUserData;
853                }
854            }
855        }
856
857        $this->set('isStripeUser', $this->isStripeUser);
858        $this->set('isStripeAppleUser', $this->isStripeAppleUser);
859        $this->set('isStripeGoogleUser', $this->isStripeGoogleUser);
860        $this->set('isPayPalUser', $this->isPayPalUser);
861        $this->set('isAfteeUser', $this->isAfteeUser);
862        
863        //NC-5125 iso_639_1 for meta tag
864        $this->lang_iso = $this->User->getLangIso($this->request->query);
865        $this->set('lang_iso', $this->lang_iso);
866
867        // header data
868        if (
869            $this->Auth->loggedIn() && 
870            $this->request->params['action'] != "callLessonAlertandStartButton" &&
871            !$this->request->is('ajax') &&
872            (
873                isset($this->params['controller']) && 
874                ($currentPageController != 'class' && $currentPageController != 'htmltextbook' && $currentPageController != 'cs' && !($currentPageController == 'account' && $this->request->params['action'] == 'index'))
875            ) &&
876            !(strpos($this->params->url, 'paypal/create-billing-agreement-token') !== false) &&
877            !(strpos($this->params->url, 'Payment/zeuspayGetChallenge') !== false) &&
878            !(strpos($this->params->url, 'faq') !== false) &&
879            !(strpos($this->params->url, 'entire_faq') !== false)
880        ) {
881            //load redis
882            App::uses('myRedis', 'Lib');
883            $redis = new myRedis();
884            
885            //set key
886            $key = 'ACTIVE_USER_PC_'.$userData['User']['id'];
887
888            //check
889            if (!$redis->get($key)) {
890                $redis->set(array(
891                    'key' => $key,
892                    'value' => 1,
893                    'expire' => 600 //10 minutes adjust to lessons
894                ));
895
896                //load model
897                $this->loadModel('UserMonitoring');
898
899                //update users monitoring
900                $this->UserMonitoring->upsert(array(
901                    'user_id' => $userData['User']['id'],
902                    'device_type' => 1 //pc
903                ));
904            }
905
906            // check user status
907            if (isset($userData['User']) && $userData['User']['status']=='9') {
908                $this->log('[NJ-65075] AppController.php L#'.__LINE__.' -- '.json_encode(array('user_data' => $userData['User'], 'request_data' => $this->request)), 'error');
909                $this->Auth->logout();
910                return $this->redirect(myTools::getUrl());
911            }
912        }
913
914        // load model
915        $this->loadModel('IpBlock');
916        $route = $this->params->url;
917
918        if ($this->IpBlock->blocked() || $this->isWithdrawn) {
919            $urlRedirect = myTools::getUrl();
920            $actionName = isset($this->request->params['action']) ? trim($this->request->params['action']) : null;
921
922            // pc if login
923            if ($this->Auth->loggedIn()) {
924                if (
925                    strtolower($actionName) != 'getalltextbookoption' && // reservation
926                    strtolower($actionName) != 'ajaxchapter' && // reservation
927                    !$this->request->is('ajax') &&
928                    !(strpos($route, 'cs/8') !== false) &&
929                    !(strpos($route, 'cs/confirm') !== false) &&
930                    !(strpos($route, 'cs/complete') !== false) &&
931                    strtolower($currentPageController) != 'htmltextbook' &&
932                    strtolower($currentPageController) != 'faq' &&
933                    !(strpos($route, 'Payment/zeuspayGetChallenge') !== false) &&
934                    !(strpos($route, 'paypal/create-billing-agreement-token') !== false) &&
935                    !($currentPageController == 'account' && $this->request->params['action'] == 'index')
936                ) {
937
938                    $this->loadModel('LessonOnair');
939                    // if has ongoing lesson
940                    $ongoingLesson = $this->LessonOnair->find('count', array(
941                        'conditions' => array(
942                            'status' => 3,
943                            'user_id' => $this->Auth->user('id')
944                        ),
945                        'recursive' => -1
946                    ));
947
948                    if (!$ongoingLesson) {
949                        $this->Cookie->delete('stealth');
950                        $memcached = new myMemcached();
951                        $memcached->delete('user-timediff-' . $this->Auth->user('id')); //delete timezone in memcache
952                        unset($_SESSION['google_login_token']);
953                        $this->Cookie->delete('rememberMe');
954
955                        // set cookie variable to be deleted
956                        $this->Cookie->name = 'searchTeacherForm';
957                        $this->Cookie->domain = $_SERVER['SERVER_NAME'];
958                        $this->Cookie->delete('searchReserveData');
959
960                        if ($this->Session->check('promoteApp')) {
961                            $this->Session->delete('promoteApp');
962                        }
963
964                        // reset timezone check
965                        if (isset($_COOKIE['timezone_dialog_show'])) {
966                            setcookie('timezone_dialog_show', 'on', 1);
967                        }
968
969                        // NC-7459
970                        $this->Session->delete('complimentary_user_disable_links'); // delete
971
972                        $this->loadModel('UsersIpLog');
973                        $this->UsersIpLog->sendSlackNotifToBlockedLoggedInUser(array('userId' => $userData['User']['id']));
974
975                        if (
976                            strtolower($this->request->params['controller']) == 'cs' ||
977                            (strtolower($this->request->params['controller']) == 'localize' && strtolower($actionName) == 'index') ||
978                            (strtolower($this->request->params['controller']) == 'entirefaq' && strtolower($actionName) == 'index')
979                        ) { // faq and cs
980                            if(isset($userData['User']['studysapuri_id'])) {
981                                $urlRedirect .= '/faq/category';
982                            } else {
983                                $urlRedirect .= '/cs/8';
984                            }
985                            return $this->redirect($urlRedirect);
986                        }
987                        $this->log('[NJ-65075] AppController.php L#'.__LINE__.' -- '.json_encode(array('user_data' => $userData['User'], 'request_data' => $this->request)), 'error');
988                        $this->Auth->logout();
989                        return $this->redirect($urlRedirect);
990                    }
991                }
992            // pc non login
993            } elseif ( 
994                !$this->request->is('ajax') &&
995                !empty($route) &&
996                !in_array($route, array('login')) &&
997                !(strpos($route, 'cs/8') !== false) &&
998                !(strpos($route, 'cs/confirm') !== false) &&
999                !(strpos($route, 'mobapp/close') !== false) &&
1000                !(strpos($route, 'cs/complete') !== false) &&
1001                !(strpos($route, 'mobapp/register') !== false) &&
1002                !(strpos($route, 'mobapp/home') !== false) &&
1003                !(strpos($route, 'paypal/create-billing-agreement-token') !== false) &&
1004                !isset($this->request->query['appVersion']) &&
1005                !isset($this->request->query['deviceType']) &&
1006                !isset($this->request->query['token']) &&
1007                strtolower($currentPageController) != 'htmltextbook' &&
1008                strtolower($currentPageController) != 'mobapp' &&
1009                !in_array($route, Configure::read('main_supported_language')) &&
1010                !(strpos($route, 'Payment/zeuspayGetChallenge') !== false)
1011            ) {
1012                if (
1013                        strtolower($this->request->params['controller']) == 'cs' || 
1014                        strtolower($this->request->params['controller']) == 'localize'
1015                    ) { // faq and cs
1016                    $urlRedirect .= '/cs/8'; 
1017                }
1018                return $this->redirect($urlRedirect);
1019            // web view
1020            } elseif (
1021                !$this->request->is('ajax') &&
1022                strtolower($currentPageController) != 'htmltextbook' &&
1023                strtolower($currentPageController) != 'class' &&
1024                (strtolower($currentPageController) == 'mobapp' || ($currentPageController == 'payment' && $actionName == 'mobapp_credit_charge_form')) &&
1025                !(strpos($route, 'mobapp/home') !== false) &&
1026                !(strpos($route, 'mobapp/close') !== false) &&
1027                !in_array($route, array('login')) &&
1028                !(strpos($route, 'paypal/create-billing-agreement-token') !== false) &&
1029                !empty($route) &&
1030                !in_array($route, Configure::read('main_supported_language'))
1031
1032            ) {
1033                if (
1034                    isset($this->request->query['token']) &&
1035                    !(strpos($route, 'mobapp/register') !== false)
1036                ) {
1037                    if ((
1038                            strpos($route, 'mobapp/cs') !== false ||
1039                            strpos($route, 'mobapp/confirm') !== false
1040                        ) &&
1041                        isset($this->request->query['c']) &&
1042                        $this->request->query['c'] == 8
1043                    ) {
1044                        // do nothing
1045                    } else if((
1046                                strpos($route, 'mobapp/cs') !== false ||
1047                                strpos($route, 'mobapp/confirm') !== false ||
1048                                strpos($route, 'mobapp/menu_inquiry') !== false ||
1049                                strpos($route, 'mobapp/faq') !== false
1050                            ) &&
1051                            (empty($this->request->query['c']) || (isset($this->request->query['c']) && $this->request->query['c'] != 8))
1052                    ) {
1053                        $urlRedirect = myTools::getUrl() . '/mobapp/cs' . myTools::getMobappToken($_GET) . '&c=8';
1054                        return $this->redirect($urlRedirect);
1055                    } else {
1056                        $appVersion = isset($this->request->query['appVersion']) && !empty($this->request->query['appVersion']) ? $this->request->query['appVersion'] : 0;
1057                        $deviceType = isset($this->request->query['deviceType']) && !empty($this->request->query['deviceType']) ? $this->request->query['deviceType'] : 0;
1058                        if(!empty($appVersion) && !empty($deviceType)) {
1059                            if (in_array($deviceType, [1,2,3])) {
1060                                $appVersionCompare = version_compare($appVersion, Configure::read('ip_block_app_version')[$deviceType], '<');
1061                                if (!$appVersionCompare) {
1062                                    return $this->redirect('nativecamp://view/is_blocked');
1063                                }
1064                            }
1065                        }
1066                    }
1067                    
1068                } else {
1069                    $urlRedirect = myTools::getUrl() . '/mobapp/home' . myTools::getMobappToken($_GET);
1070                    if (
1071                        strpos($route, 'mobapp/home') !== false ||
1072                        (
1073                            (
1074                                strpos($route, 'mobapp/cs') !== false ||
1075                                strpos($route, 'mobapp/confirm') !== false
1076                            ) &&
1077                            isset($this->request->query['c']) &&
1078                            $this->request->query['c'] == 8
1079                        )
1080                    ) {
1081                        // do nothing
1082                    } else {
1083                        // for mobapp cs blocked ip address
1084                        $route = parse_url($route, PHP_URL_PATH);
1085                        if (
1086                                strpos($route, 'mobapp/cs') !== false || 
1087                                strpos($route, 'mobapp/faq') !== false 
1088                            ) {
1089                            $urlRedirect = myTools::getUrl() . '/mobapp/cs' . myTools::getMobappToken($_GET) . '&c=8';
1090                        }
1091
1092                        return $this->redirect($urlRedirect);
1093                    }
1094                }
1095            }
1096        }
1097
1098        // 4372 textbook name cached
1099        $textbookNamesCached = $memcached->get(Configure::read('textbook_names_cache_key'));
1100
1101        // set shared userData
1102        $this->sharedUserData = $userData;
1103
1104        // set userCurrencyCode
1105
1106        $defaultCurrencyCode = Configure::read('default.user_currency');
1107        $allowedCurrencies = Configure::read('pc_allowed_currencies');
1108        $currencyCode = isset($allowedCurrencies[$this->localizeDir]) ? $allowedCurrencies[$this->localizeDir] : $defaultCurrencyCode;
1109
1110        if(isset($this->mobAppUserData) && $this->mobAppUserData['User']['currency_code']) {
1111            $setCurrencyCode = $this->mobAppUserData['User']['currency_code'];
1112        } else {
1113            $setCurrencyCode = isset($this->sharedUserData) && is_array($this->sharedUserData) && $this->sharedUserData['User']['currency_code'] ? $this->sharedUserData['User']['currency_code'] : $currencyCode;
1114        }
1115        $this->set('userSetCurrencyCode', $setCurrencyCode);
1116        
1117        myTools::setCurrencyCode($setCurrencyCode);
1118        
1119        // remove success session from registration
1120        $this->Session->delete('registerSuccessEnd');
1121        $this->set('textbookNamesCached', $textbookNamesCached);
1122        $this->set('auth', $this->Auth);
1123        $this->set(compact('userData'));
1124        $this->set('isMobileRequestHandler', $this->RequestHandler->isMobile());
1125        //timezone data
1126        $this->set(array(
1127            'timeDiff' => $this->timeDiff,
1128            'timeDiffSecond' => $this->timeDiffSecond,
1129            'displayTime' => $this->displayTime,
1130            'utcOffset' => $this->utcOffset,
1131            'allowedCoupon' => $this->allowedCoupon ? true : false
1132        ));
1133        
1134        // NC-7459 check complimentary user's status, force redirect to conversion page if expired.
1135        // @TODOs check mobapp and payment, lessons, sp pages.
1136        // callLessonAlertandStartButton
1137        // ($currentPageController != 'class' && $currentPageController != 'htmltextbook')
1138        $excludeControllers = array(
1139            "mobapp", 
1140            "payment", 
1141            "cs", 
1142            "lessonfinish", 
1143            "class", 
1144            "htmltextbook", 
1145            "register"
1146        );
1147        $excludeActions = array(
1148            "continuoususe_advertising", 
1149            "continuoususe_promotion", 
1150            "logout", 
1151            "callLessonAlertandStartButton", 
1152            "credit_form", 
1153            "credit_form_process", 
1154            "credit_form_success", 
1155            "complete", 
1156            "change_to_premium", 
1157            "premium", 
1158            "wp_credit_form", 
1159            "notice_to_user", 
1160            "spcreditform"
1161        );
1162
1163        $this->CompCodeUsage->openDBReplica();
1164        $getUserCompStatus = $this->CompCodeUsage->find('first', array(
1165                'fields' => [
1166                    'CompCodeUsage.code',
1167                    'CompCodeUsage.expire_flg',
1168                    'CompCodeUsage.used_at'
1169                ],
1170                'recursive' => -1,
1171                'conditions' => array('CompCodeUsage.user_id' => $this->Auth->user('id'),
1172                 'CompCodeUsage.active_flg' => 1)
1173            ));
1174        $this->CompCodeUsage->closeDBReplica();
1175
1176        $complimentaryCode = "";
1177        $chargeDate = "";
1178        $compCodeIsExpired = "";
1179        if(!empty($getUserCompStatus)){
1180            $complimentaryCode = $getUserCompStatus['CompCodeUsage']['code'];
1181            $chargeDate = $getUserCompStatus['CompCodeUsage']['used_at'];
1182            $compCodeIsExpired = $getUserCompStatus['CompCodeUsage']['expire_flg'];
1183        }
1184
1185        $userDataForCompStatus = array(
1186            'id' => $this->Auth->user('id'),
1187            'complimentary_code' => $complimentaryCode,
1188            'first_charge_date' => $chargeDate
1189        );
1190        
1191        $currentController = isset($this->request->params['controller']) ? trim(strtolower($this->request->params['controller'])) : null;
1192        $currentAction = isset($this->request->params['action']) ? trim($this->request->params['action']) : null;
1193        $conditions = $this->Auth->loggedIn()
1194        && isset($userData['User'])
1195        && isset($complimentaryCode)
1196        && isset($userData['User']['payment_plan_id'])
1197        && $userData['User']['payment_plan_id'] == Configure::read('payment_plans.complimentary_plan')
1198        && !$this->request->is('ajax')
1199        && !in_array($currentController, $excludeControllers)
1200        && !in_array($currentAction, $excludeActions);
1201
1202        $this->loadModel('ComplimentaryCode');
1203        $comPlanData = $this->ComplimentaryCode->getUserComplimentaryPlanStatus($userDataForCompStatus);
1204        // this code is for redirection to mypage if condition is not satisfied
1205        if (isset($comPlanData['complimentary_plan_conversion_url']) && 
1206            ($comPlanData['complimentary_plan_conversion_url'] === '/continuoususe/advertising' || 
1207            $comPlanData['complimentary_plan_conversion_url'] === '/continuoususe/promotion')) {
1208            $conditions = $conditions && $compCodeIsExpired;
1209        }
1210        
1211
1212        if ($conditions) {
1213            // check
1214            if (
1215                isset($comPlanData['compliemntary_plan_can_lesson'])
1216                && !$comPlanData['compliemntary_plan_can_lesson']
1217                && isset($comPlanData['complimentary_plan_conversion_url'])
1218            ) {
1219                // $comPlanData['complimentary_plan_conversion_url'] = "/continuoususe/promotion";
1220                $complimentaryConversionType = isset($comPlanData['template_type']) ? $comPlanData['template_type'] : 0;
1221                $coin_award = isset($comPlanData['coin_award']) ? $comPlanData['coin_award'] : 0;
1222                $this->Session->write('complimentary_user_disable_links', true);
1223                return $this->redirect(myTools::getUrl() . $comPlanData['complimentary_plan_conversion_url']);
1224            }
1225        }
1226
1227
1228        // parent avatar json data
1229        $avatarJson = null;
1230        $avS3PageCont = array('mypage','waiting','favorite');
1231        $avS3PageActions = array('index');
1232        if ( 
1233            $this->Auth->loggedIn() && 
1234            in_array($currentController, $avS3PageCont) && 
1235            in_array($currentAction, $avS3PageActions)
1236        ) {
1237            $avatarJson = TeacherTable::getAvatarChildJson();
1238        }
1239
1240        // NJ-51
1241        $lessonPriorityControllerArr = Configure::read('priority_lesson_group_data_info.web.controller');
1242        $lessonPriorityActionArr = Configure::read('priority_lesson_group_data_info.web.action');
1243        if ( 
1244            $this->Auth->loggedIn() && 
1245            in_array($currentController, $lessonPriorityControllerArr) && 
1246            in_array($currentAction, $lessonPriorityActionArr)
1247        ) {
1248            $this->studentLessonPriorityTimeDelayInSeconds = $this->User->userPriorityDelay( array( 'user_id' => $this->Auth->user('id') ) );
1249        }
1250
1251        // delete diablelink flag, if navigate to not restricted page.
1252        if (
1253            !in_array($currentAction, $excludeActions)
1254            && !$this->request->is('ajax')
1255        ) {
1256            $this->Session->delete('complimentary_user_disable_links'); // delete
1257        }
1258
1259        // check if there is/are unsave user lesson connection   data.
1260        if (!$this->request->is('ajax')) {
1261            $cookieKey = 'user_lesson_connection_speed_unsave_data';
1262
1263            // - delete cookie if exists
1264            if (isset($_COOKIE[$cookieKey])) {
1265                if ($this->LessonConnectionSpeedDetail->updateConnectionSpeedInfo($cookieKey, 'user')) {
1266                    unset($_COOKIE[$cookieKey]);
1267                    setcookie($cookieKey, null, -1, '/');
1268                }
1269            }
1270        }
1271
1272        $this->isStudySapuriUser = ($this->isStudySapuriTosUser || $this->studySapuriId);
1273        $this->allowedCurrencies = Configure::read('pc_allowed_currencies');
1274        // NC-7922 : Stasapu cs admin domains not allow access
1275        $this->checkStasapuDomain();
1276        // - set current controller and action
1277        $this->set('avatarJson', $avatarJson);
1278        $this->set('current_controller', $currentController);
1279        $this->set('current_action', $currentAction);
1280        $this->set('studySapuriId', $this->studySapuriId);
1281        $this->set('isStudySapuriTosUser', $this->isStudySapuriTosUser);
1282        $this->set('isStudySapuriUser', $this->isStudySapuriUser);
1283        $this->set('studentLessonPriorityTimeDelayInSeconds', $this->studentLessonPriorityTimeDelayInSeconds);
1284        $this->set('isTemporaryPassword', $this->isTemporaryPassword);
1285        $this->set('defaultCameraSetting', $this->defaultCameraSetting);
1286        $this->set('userCDNPath', Configure::read('user.cdn_path_webroot'));
1287                
1288        //NJ-3882
1289        if (isset($userObj) && $userObj) {
1290            $membershipType = $userObj->getMembershipTypeIndex();
1291            $this->userMembershipType = $membershipType;
1292            $this->set('membershipType', $membershipType);
1293        }
1294
1295        //NJ-13670 New Year Part 1 campaign
1296        $newYear1DesignCampaign = false;
1297        $newYear1CampDateArr = Configure::read('campaign_config.new_year_part_1.period');
1298        if (
1299            (
1300                isset($userObj) && $userObj 
1301                && in_array($userObj->getMembershipTypeIndex(), Configure::read('campaign_config.new_year_part_1.design_valid_memberships'))
1302                && time() >= strtotime($newYear1CampDateArr['start']) && time() <= strtotime($newYear1CampDateArr['end'])
1303            )
1304            || (
1305                (!isset($userObj) || !$userObj)
1306                && time() >= strtotime($newYear1CampDateArr['start']) && time() <= strtotime($newYear1CampDateArr['end'])
1307            )
1308        ) {
1309            $newYear1DesignCampaign = true;
1310        }
1311        $this->set('newYear1DesignCampaign', $newYear1DesignCampaign);
1312
1313        //NJ-14237 Amazon Gift campaign
1314        $amazonGiftCampaign = false;
1315        $amazonGiftCampDateArr = Configure::read('campaign_config.amazongift.period');
1316        if (
1317            (
1318                isset($userObj) && $userObj 
1319                && !$this->isStudySapuriUser
1320                && in_array($userObj->getMembershipTypeIndex(), Configure::read('campaign_config.amazongift.valid_memberships'))
1321                && time() >= strtotime($amazonGiftCampDateArr['start']) && time() <= strtotime($amazonGiftCampDateArr['end'])
1322                && $userObj->currency_code == Configure::read('default.user_currency')
1323                && $this->localizeDir == Configure::read('default.user_language')
1324                && !$this->isStudySapuriUser
1325                && $this->action != 'createAccountStudysapuri'
1326            )
1327            || (
1328                (!isset($userObj) || !$userObj)
1329                && time() >= strtotime($amazonGiftCampDateArr['start']) && time() <= strtotime($amazonGiftCampDateArr['end'])
1330                && $this->localizeDir == Configure::read('default.user_language')
1331                && !$this->isStudySapuriUser
1332                && $this->action != 'createAccountStudysapuri'
1333            )
1334        ) {
1335            if($route == '' || strtolower($route) == 'register'){
1336                $amazonGiftCampaign = true;
1337            }
1338        }
1339        $this->set('amazonGiftCampaign', $amazonGiftCampaign);
1340
1341        $googleTagManager = Configure::read('google_tag_manager.default');
1342        if ($firstSegment) {
1343            $globalLanguageAllowed = Configure::read('global_language.allowed_list');
1344
1345            if (in_array($this->localizeDir, $globalLanguageAllowed)) {
1346                $googleTagManager = Configure::read('google_tag_manager.oversies');
1347            } else if (strpos($firstSegment, 'tutors') !== false || strpos($firstSegment, 'recruit') !== false) {
1348                $googleTagManager = Configure::read('google_tag_manager.others');
1349            }
1350        }
1351        $this->set('googleTagManager', $googleTagManager);
1352
1353        if(
1354            (isset($this->request->query['deviceType']) && $this->request->query['deviceType']) &&
1355            (isset($this->request->query['appVersion']) && $this->request->query['appVersion'])) {
1356            $this->NCPlusPositionUrlScheme($this->request->query['appVersion'], $this->request->query['deviceType']);
1357        }
1358        // NJ-37156: Set flag for lite plan users in all pages
1359        $isLitePlanUser = is_array($userData) && in_array($userData['User']['payment_plan_id'], Configure::read('lite_payment_plans')) ? 1 : 0;
1360        $this->set('isLitePlanUser', $isLitePlanUser);
1361
1362        // Study Abroad
1363        $ryugakuAllowedLang = Configure::read('ryugaku_language.allowed_list');
1364        if (in_array($currentController, array('studyabroad', 'studyabroadcreateestimate'))  && !in_array($this->localizeDir, $ryugakuAllowedLang)) {
1365            return $this->redirect('/');
1366        }
1367
1368        //- NJ-27262
1369        //- Redirect chocotto user to download page if logs on PC/SP
1370        if($this->Auth->loggedIn()) {
1371
1372            if (isset($userObj) && $userObj && isset($userObj->payment_plan_id)) {
1373                $isChocottoUser = in_array($userObj->payment_plan_id, [
1374                    Configure::read('payment_plans.free_trial_chocotto'), 
1375                    Configure::read('payment_plans.chocotto_plan')
1376                ]);
1377                
1378                // - check if not accessing study abroad
1379                $notStudyAbroadAccess = (
1380                    (strpos($route, 'study_abroad') === false) 
1381                    && !$this->request->is('ajax') 
1382                    && !in_array($currentController, array('studyabroad', 'studyabroadcreateestimate', 'studyabroadfavorite'))
1383                );
1384
1385                if($isChocottoUser && $notStudyAbroadAccess) {
1386                    $this->log('[NJ-65075] AppController.php L#'.__LINE__.' -- '.json_encode(array('user_data' => $userObj, 'request_data' => $this->request, 'param_data' => $this->params)), 'error');
1387                    $this->Auth->logout();
1388                    $this->redirect('/chocotto_camp_success');
1389                }
1390            }
1391        }
1392        
1393        // Initialize $userCorpId either $appUserData or $userData
1394        $userCorpId = null;
1395        if (isset($appUserData['User']['corporate_id']) && !empty($appUserData['User']['corporate_id'])) {
1396            $userCorpId = $appUserData['User']['corporate_id'];
1397        } elseif (isset($userData['User']['corporate_id']) && !empty($userData['User']['corporate_id'])) {
1398            $userCorpId = $userData['User']['corporate_id'];
1399        }
1400
1401        // Check if the user is corporate, retrieve the payment method if corporate_id exists
1402        if (isset($userCorpId) && !empty($userCorpId)) {
1403            $corpIndPayment = $this->Corporate->getPaymentMethod($userCorpId);
1404            if ($corpIndPayment == 1) {
1405                $this->isIndividualCorp = true;
1406            }
1407        }
1408
1409        // Set the variable to check if the user is an individual corporate
1410        $this->set('isIndividualCorp', $this->isIndividualCorp);
1411
1412        // check if Stripe is Supported
1413        $this->checkStripeSupported($userData);
1414        
1415        $custom_lang_format_flag= false;
1416        if(isset($this->localizeDir) && in_array($this->localizeDir, Configure::read("custom_lang_format_support"))) { 
1417            $custom_lang_format_flag = true;
1418        }
1419        $this->set("custom_lang_format_flag",$custom_lang_format_flag);
1420
1421        $currentLang_iso = $this->Session->read('Config.language_iso_1');
1422        
1423        // NJ-57390 - redirect to register or download app 
1424        if (!$this->request->is('post') && !$this->request->is('ajax') && !isset($this->request->query['appVersion'])) {
1425            if(!in_array($this->name, ['Home', 'Register', 'Login', 'Mobapp', 'MobappInquiry','SpTextbook', 'HtmlTextbook', 'Account']) && in_array($currentLang_iso, ['fr', 'de', 'zh-cn'])) {
1426                $url = myTools::getUrl();
1427
1428                if($this->Auth->loggedIn()) {
1429                    $this->log('[NJ-65075] AppController.php L#'.__LINE__.' -- '.json_encode(array('user_data' => $userData, 'lang_iso' => $currentLang_iso, 'request_data' => $this->request)), 'error');
1430                    $this->Auth->logout();
1431                    return $this->redirect($url . '/' . $currentLang_iso . '?download_app=true');
1432                } else {
1433                    return $this->redirect($url . '/' . $currentLang_iso . '/register');
1434                }
1435            }
1436        }
1437    }
1438    
1439    public function setLocalization() {
1440        $source = $this->Cookie->read('source');
1441        if (empty($source)) {
1442            $source = isset($_GET['source']) ? $_GET['source'] : '';
1443        }
1444
1445        // check if demohtmltextbook view and has lang params
1446        if(
1447            isset($this->request->params['controller']) && 
1448            strtolower($this->request->params['controller']) == 'demohtmltextbook'
1449        ){
1450            if(isset($this->request->query['lang']) && $this->request->query['lang']){
1451                $this->localizeDir = $this->request->query['lang'];
1452            }else{
1453                $this->localizeDir = Configure::read('default.user_language');
1454            }
1455
1456        // - if has localize directory - main override!!
1457        } else if (isset($this->request->data['localizeDir']) && mb_strlen($this->request->data['localizeDir'])) {
1458            $this->localizeDir = $this->request->data['localizeDir'];
1459
1460        // - if AJAX and cookie contains value
1461        } else if (
1462            $this->request->is('ajax') 
1463            && $this->Cookie->check('localizeDir')
1464            && (mb_check_encoding($this->Cookie->read('localizeDir'), 'UTF-8')  && strpos($this->Cookie->read('localizeDir'), '�') == false)
1465        ) {
1466            $this->localizeDir = $this->Cookie->read('localizeDir');
1467            
1468            
1469        // - else
1470        } else {
1471            // - if has language parameter
1472            if (
1473                ($this->request && isset($this->request->language) && $this->request->language != Configure::read('default.user_language')) || 
1474                ($this->localizeDir != Configure::read('default.user_language'))
1475            ) {
1476                $this->localizeDir = $this->request->language;
1477
1478            // - whitelisted actions
1479            } else if (
1480                // - if has valid action
1481                isset($this->request->params['action']) && $this->Cookie->check('localizeDir') 
1482
1483                // - valid format
1484                && (mb_check_encoding($this->Cookie->read('localizeDir'), 'UTF-8') && strpos($this->Cookie->read('localizeDir'), '�') == false)
1485                
1486                // - if not home
1487                && !($this->request->params['action'] == "index" && $this->request->params['controller'] == "home")
1488                && !($this->request->params['action'] == "price_mobapp" && $this->request->params['controller'] == "Usage")
1489                && !($this->request->params['action'] == "features" && $this->request->params['controller'] == "mobapp")
1490                && !($this->request->params['action'] == "service_mobapp" && $this->request->params['controller'] == "Usage")
1491                && !($this->request->params['action'] == "menu_inquiry" && $this->request->params['controller'] == "Mobapp")
1492                && !($this->request->params['action'] == "favorite_teachers" && $this->request->params['controller'] == "Mobapp")
1493                && $source != 'okpanda'
1494            ) {
1495                $this->localizeDir = $this->Cookie->read('localizeDir');
1496
1497            // - if has language "la" in query
1498            } else if (
1499                isset($this->request->query['la']) && $this->request->query['la'] != Configure::read('default.user_language')
1500                
1501                // - if home
1502                && (
1503                    ($this->request->params['action'] == "index" && $this->request->params['controller'] == "home") ||
1504                    (isset($this->request->params['overrideLocalizeDir']) && $this->request->params['overrideLocalizeDir']) ||
1505                    ($this->request->params['action'] == "price_mobapp" && $this->request->params['controller'] == "Usage") ||
1506                    ($this->request->params['action'] == "features" && $this->request->params['controller'] == "mobapp") ||
1507                    ($this->request->params['action'] == "service_mobapp" && $this->request->params['controller'] == "Usage") ||
1508                    ($this->request->params['action'] == "menu_inquiry" && $this->request->params['controller'] == "Mobapp") ||
1509                    $source == 'okpanda' ||
1510                    (isset($this->request->params['overrideLocalizeDir']) && $this->request->params['overrideLocalizeDir'])
1511                )
1512            ) {
1513                $this->localizeDir = $this->request->query['la'];
1514            }
1515        }
1516
1517        // get allowed languages
1518        $allowedLanguages = array_flip(Configure::read('pc_allowed_currencies'));
1519
1520        // get currency code
1521        $this->loadModel('GeoIPCountryCurrency');
1522        $currencyCode = $this->GeoIPCountryCurrency->getCurrencyCode();
1523        $this->localizeIPLang = $currencyCode;
1524
1525        $eurAllowedLanguageCodes = array_keys(Configure::read('pc_allowed_currencies'), 'EUR'); // ['fr', 'de'] for now at NJ-57390
1526        $countryCode = $this->GeoIPCountryCurrency->getCountryCode();
1527
1528        if (!empty($this->params->params['language']) && $this->params->params['language'] == 'zh-cn') {
1529            $ipLanguage = $this->params->params['language'];
1530        } else if(in_array(strtolower($countryCode), $eurAllowedLanguageCodes)) {
1531            $ipLanguage = strtolower($countryCode);
1532        } else {
1533            $ipLanguage = !empty($currencyCode) && $currencyCode != 'USD' && isset($allowedLanguages[$currencyCode]) ? $allowedLanguages[$currencyCode] : Configure::read('default.user_language');
1534        }
1535
1536        $controller = $this->params->params['controller'];
1537        $action = $this->params->params['action'];
1538        $route = $this->params->url;
1539        $ipRestrictionFlg = true;
1540
1541        // if vietnam language
1542        if ($ipLanguage == 'vi') {
1543            // check if vnStealth is set
1544            if (isset($this->request->query['vnStealth'])) {
1545                if ($this->request->query['vnStealth'] == 'off') {
1546                    $this->Cookie->delete('excludeIpRestriction');
1547                } elseif ($this->request->query['vnStealth'] == 'on') {
1548                    $this->Cookie->write('excludeIpRestriction', true);
1549                }
1550            }
1551        } else {
1552            $this->Cookie->delete('excludeIpRestriction');
1553        }
1554
1555        if ($this->Cookie->read('excludeIpRestriction')) {
1556            $ipRestrictionFlg = false;
1557        }
1558
1559        // restriction for france and germany, this will not redirect to /de or /fr if ip is germany or france
1560        if (in_array($ipLanguage, ['fr', 'de'])) {
1561            $ipRestrictionFlg = false;
1562        }
1563
1564        // change language based on ip lang if
1565        // if ip language is ko or zh-tw and request language is not equals to ip language
1566        if (
1567            !$this->request->is('post') &&
1568            !$this->request->is('ajax') &&
1569            !isset($this->request->query['la']) &&
1570            in_array($ipLanguage, Configure::read('global_language.allowed_list')) &&
1571            !in_array($action, array('sendDLlink', 'zeuspay', 'corporateZeuspay', 'getWPPaymentResult', 'getAfteePaymentResult', 'stripepay', 'stripepay_manual')) &&
1572            $controller != 'Api' &&
1573            strtolower($controller) != 'mobapp' &&
1574            !(strpos($route, 'mobapp/') !== false) &&
1575            !(strpos($route, 'HtmlTextbook/') !== false) && // for pc textbook
1576            !(strpos($route, 'sp/textbook/') !== false) && // for app textbook
1577            !(strpos($route, 'textbook/getSpeech/') !== false) && // for audio
1578            $ipRestrictionFlg
1579            || // if url was sent from sns sharing
1580            (
1581                isset($_GET["nc_share_ref"]) &&
1582                $_GET["nc_share_ref"] == "nc_sns_share" &&
1583                !(
1584                    (strpos($_SERVER["HTTP_USER_AGENT"], 'facebookexternalhit') !== false) ||
1585                    (strpos($_SERVER["HTTP_USER_AGENT"], 'Twitterbot') !== false) ||
1586                    (strpos($_SERVER["HTTP_USER_AGENT"], 'line-poker') !== false)
1587                )
1588            )
1589            && $source != 'okpanda'
1590        ) {
1591            $isPaymentUrl =  (strpos($route, 'payment/mobapp_') !== false);
1592            if (!empty($this->request->language) && $this->request->language != $ipLanguage && !$isPaymentUrl) {
1593                return $this->redirectUsingIpLang($ipLanguage);
1594            } else {
1595                if (
1596                    $this->checkControllerActionExist($controller, $action) &&
1597                    $this->request->language != $ipLanguage &&
1598                    !$isPaymentUrl
1599                ) {
1600                    return $this->redirectUsingIpLang($ipLanguage);
1601                }
1602            }
1603        }
1604
1605        //NJ-32821
1606        $referringURL = @$_SERVER['HTTP_REFERER'];
1607        // Check if came from zh-tw blog
1608        if (!empty($referringURL)) {
1609            $pattern = '/\/([^\/]+)\/blog\//';
1610            if (preg_match($pattern, $referringURL, $matches) && count($matches) > 1) {
1611                   $zh_tw = $matches[1];
1612                   if(!empty($zh_tw) && $zh_tw == "zh-tw") {
1613                       $this->localizeDir = $zh_tw;
1614                    //$this->log("Redirect : " . $url , "debug");
1615                   }
1616            } 
1617        } 
1618        
1619        // - set cookie information
1620        $this->Cookie->write('localizeDir', $this->localizeDir);
1621        Configure::write('default.localization', $this->localizeDir);
1622        $this->set('localizeDir', $this->localizeDir);
1623
1624        // - if has default language
1625        if ( $this->localizeDir != Configure::read('default.user_language') ) {
1626            if (
1627                // - if not supported
1628                (
1629                    !in_array($this->localizeDir, Configure::read('global_language.allowed_list')) 
1630                    && $this->request->params['controller'] != 'home'
1631                )
1632
1633                // - and not static page
1634                && (
1635                    $this->request->params['controller'] != 'static' 
1636                    && $this->request->params['action'] != 'privacy' 
1637                    && $this->request->params['action'] != 'privacy'
1638                )
1639
1640                // - and not api controller
1641                && (
1642                    $this->request->params['controller'] != 'Api' 
1643                    && $this->request->params['action'] != 'sendDLlink'
1644                )
1645
1646                // - if not mobapp link
1647                && (
1648                    strtolower($this->request->params['controller']) != 'mobapp' 
1649                )
1650
1651                // - if not mobapp link
1652                && (
1653                    strtolower($this->request->params['controller']) != 'payment' 
1654                    && $this->request->params['action'] != 'getHostedPage'
1655                )
1656
1657                // - if not cs page
1658                && (
1659                    strtolower($this->request->params['controller']) != 'cs' 
1660                )
1661
1662                // - if not reregister
1663                && (
1664                    strtolower($this->request->params['controller']) != 'reregister' 
1665                )
1666                
1667                // - if not textbook
1668                && (
1669                    strtolower($this->request->params['controller']) != 'htmltextbook' 
1670                )
1671
1672                
1673                // NJ-11650 - if not FAQ
1674                && (
1675                    strtolower($this->request->params['controller']) != 'entirefaq' 
1676                )
1677                // - if not textbook
1678                && (
1679                    strtolower($this->request->params['controller']) != 'demohtmltextbook' 
1680                )
1681
1682                // - if login + register from Okpanda
1683                && $source != 'okpanda'
1684
1685            ) {
1686                if ($this->Auth->loggedIn()) {
1687                    $this->log('[NJ-65075] AppController.php L#'.__LINE__.' -- '.json_encode(array('localizeDir' => $this->localizeDir, 'request_data' => $this->request)), 'error');
1688                    return $this->redirect($this->Auth->logout());
1689                }
1690                return $this->redirect('/');
1691            }
1692
1693            $this->baseUrl =  myTools::getUrl() . '/' . Configure::read('default.localization');
1694            $this->set('noIndexFlg', true);
1695            
1696            $lang_iso_1 = $this->localizeDir;
1697            $lang_iso_1 = $lang_iso_1 == 'cz' ? 'cs' : $lang_iso_1;
1698            $language_code = $this->CountryCode->convertLangIso(array(
1699                'language_code' => $lang_iso_1,
1700                'target_iso' => 2
1701            ));
1702            $this->Session->write('Config.language', $language_code);
1703            $this->Session->write('Config.language_iso_1', $lang_iso_1);
1704            $this->set('html_lang_iso_1', $lang_iso_1);
1705        } else {
1706
1707            $this->baseUrl =  myTools::getUrl();
1708            $this->set('html_lang_iso_1', $this->localizeDir);    
1709        }
1710
1711        // - apply translation for error message
1712        $this->Auth->authError = __d("login", "再度ログインしなおしてください。");
1713        $this->Auth->loginError = __d("login", "メールアドレス、またはパスワードに誤りがあります。");
1714    }
1715
1716    /**
1717     * redirect with language based on ip address
1718     * @param string  $ipLanguage
1719     * @return string new rurl
1720     */
1721    private function redirectUsingIpLang($ipLanguage) {
1722        $webUrl = $_SERVER['REQUEST_URI'];
1723        $segment = explode('/', $webUrl);
1724
1725        $isSNSShare = false;
1726        // if url has nc_share_ref or shared to SNS 
1727        // parse url to remove query for sns share "nc_share_ref"
1728        if(isset($_GET["nc_share_ref"]) && $_GET["nc_share_ref"]== "nc_sns_share" ){
1729            $parsedUrl = parse_url($webUrl);
1730            parse_str( $parsedUrl['query'], $parameters ); 
1731            unset( $parameters['nc_share_ref'] ); 
1732            $newQuery = http_build_query($parameters);
1733            $isSNSShare = true;
1734        }
1735        
1736
1737        if (!isset($this->request->language)) {
1738            $segment[0] = '/' . $ipLanguage;
1739            $newUrl = implode('/', $segment);
1740            // apply new url if SNS share
1741            if($isSNSShare){
1742                $newUrl = '/' . $ipLanguage . $parsedUrl['path'] .'?'. $newQuery;
1743            }
1744        } else {
1745            $segment[1] = str_replace($segment[1], $ipLanguage, $segment[1]);
1746            $newUrl = implode('/', $segment);
1747            // apply new url if SNS share
1748            if($isSNSShare){
1749                $newParsedUrl = rtrim(str_replace('/'.$this->request->language, '', $parsedUrl['path']), '/');
1750                $newUrl = '/' .  str_replace($segment[1], $ipLanguage, $segment[1]) . $newParsedUrl .'?'. $newQuery;
1751            }
1752        }
1753
1754        return parent::redirect(myTools::getUrl() . $newUrl, null, false);
1755    }
1756
1757    public function redirect($url, $status = null, $exit = true) {
1758        //override redirect to login page with status 301
1759        if (($url == '/login' || $url == myTools::getUrl() . '/user/login') && strtolower($this->request->params['controller']) != 'login') {
1760            $this->response->disableCache();
1761            $url = myTools::getUrl() . '/user/login';
1762            $status = 301;
1763        }
1764
1765        // - if contains mobapp, do not do any processing
1766        if (is_string($url) && strpos($url, "/mobapp") !== false) {
1767            return parent::redirect($url, $status, $exit);
1768        }
1769        
1770        # redirect to Localized URL
1771        if (
1772            $this->localizeDir != 'ja' &&
1773            ((!is_array($url) && $this->localizeDir && strpos($url, "/" . $this->localizeDir) === false) ||
1774            (is_array($url) && $this->localizeDir && !isset($url['language'])))
1775        ) {
1776
1777            if (is_array($url)) {
1778                $url['language'] = $this->localizeDir;
1779            } else {
1780                $parseDomain = false;
1781                #if not nativecamp site avoid editing url
1782                if (strpos($url, 'http://') === 0 || strpos($url, 'https://') === 0) {                    
1783                    $parseUrl = parse_url($url);
1784
1785                    if ($parseUrl['host'] != $_SERVER['HTTP_HOST']) {
1786                        return parent::redirect($url, $status, $exit);
1787                    } else {
1788                        $parseDomain = true;
1789                    }
1790                }
1791                #if not nativecamp not https
1792                if (strpos($url, 'http:') !== false && $parseDomain) {
1793                    $url = str_replace('http:', 'https:', $url);
1794                }
1795                
1796                $baseUrl = myTools::getUrl();
1797                $userDir = "/user";
1798
1799                if (strpos($url, $baseUrl) !== false && strpos($url, $userDir) !== false) {
1800                    $replace = $baseUrl . $userDir;
1801                    $replaceWith = $baseUrl . "/" . $this->localizeDir;
1802                    $url = str_replace($replace, $replaceWith, $url);
1803                } elseif (strpos($url, $baseUrl) !== false) {
1804                    $replace = $baseUrl;
1805                    $replaceWith = $baseUrl . "/" . $this->localizeDir;
1806                    $url = str_replace($replace, $replaceWith, $url);
1807                } else {
1808                    $url = $baseUrl . '/' . $this->localizeDir . $url;
1809                }
1810            }
1811        }
1812
1813        if ($this->localizeDir == 'ja') {
1814            if (is_array($url)) {
1815                unset($url['language']);
1816            } else {
1817                $checkBaseUrl = myTools::getUrl() . '/ja';
1818                
1819                if (strpos($url, $checkBaseUrl) !== false) {
1820                    $replaceWith = myTools::getUrl();
1821                    $url = str_replace($checkBaseUrl, $replaceWith, $url);
1822                } elseif (strpos($url, '/ja/') === 0) {
1823                    $url = str_replace('/ja', '', $url);
1824                }
1825            }
1826        } 
1827
1828        return parent::redirect($url, $status, false);
1829    }
1830
1831    /**
1832    * set Config.language using parameter or browser language
1833    */
1834    public function setConfigLanguage() {
1835        $lang_iso_1 = $language_code = NULL;
1836        $baseUrl = myTools::getUrl();
1837        $localizeNonLpPages = array('tos', 'privacy'); // non LP pages
1838
1839        if ($this->Auth->loggedIn()) {
1840            # get user data
1841            $user = $this->sharedUserData;
1842            $lang_iso_1 = $user['User']['native_language2'] ? $user['User']['native_language2'] : '';
1843        } else {
1844
1845            $path = $this->parseUrl['path'];
1846            $globalLang = Configure::read('global_language.list');
1847
1848            if ($path != '/') {
1849                $segment = explode('/', $path);
1850                $firstSegment = isset($segment[1])? $segment[1]:'';
1851
1852                // redirect to main url
1853                if ($firstSegment == 'ja') {
1854                    $this->log("Redirect : " . __METHOD__ . " (line " . __LINE__ . ") firstSegment = ja, " . $baseUrl , "debug");
1855                    return $this->redirect($baseUrl);
1856                }
1857
1858                // set lang iso_639_1
1859                $lang_iso_1 = $firstSegment == 'cz' ? 'cs' : (strpos($globalLang, $firstSegment) !== false ? $firstSegment : Configure::read('original.default.iso_639_1'));
1860            }
1861        }
1862
1863        if (!empty($lang_iso_1)) {
1864            //return iso_639_2 if supported language
1865            $language_code = $this->CountryCode->convertLangIso(array(
1866                'language_code' => $lang_iso_1,
1867                'target_iso' => 2
1868            ));
1869        } else {
1870            // set default
1871            $language_code = Configure::read('original.default.iso_639_2');
1872            $lang_iso_1 = Configure::read('original.default.iso_639_1');
1873        }
1874
1875        //set sessions
1876        $this->Session->write('Config.language', $language_code);
1877        $this->Session->write('Config.language_iso_1', $lang_iso_1);
1878        setcookie('lang', $lang_iso_1, 0, '/');
1879
1880        # set layoutLang_iso for url in view files
1881        $this->set('layoutLang_iso', "/".($lang_iso_1 == 'cs' ? 'cz' : $lang_iso_1));
1882
1883        // html lang
1884        $this->set('html_lang_iso_1', $lang_iso_1);
1885    }
1886
1887    // This will redirect to restriction page if currency not JPY
1888    // return $userdata = user info.
1889    public function jpyOnlyPage($user = '') {
1890        if (!empty($user)) {
1891            $userData = $user;
1892        } elseif (!empty($this->request->query['token'])) {
1893            $token = $this->request->query['token'];
1894            $userData = $this->User->findByApiToken($token);
1895        } else {
1896            return $this->redirect('/mobapp/retrypage');
1897        }
1898
1899        if (isset($userData['User'])) {
1900            $currencyCode = $userData['User']['currency_code'];
1901            $nativeLanguage = isset($userData['User']['native_language2']) ? $userData['User']['native_language2'] : Configure::read('default.user_language');
1902            // null null currency_code in DB is equal to JPY currency as default
1903            if ($currencyCode == '' || $currencyCode == Configure::read('currency_jpy')) {
1904                return $userData;
1905            } else {
1906                $languageCodeIso2 = $this->CountryCode->convertLangIso(array(
1907                    'language_code' => $nativeLanguage,
1908                    'target_iso' => 2
1909                ));
1910
1911                $confLanguage = $this->CountryCode->checkGlobalLanguage(array(
1912                    'language_code' => $nativeLanguage,
1913                    'unset_language_code' => array('ja')
1914                ));
1915
1916                $controller = strtolower($this->params->params['controller']);
1917
1918                if(
1919                    in_array($controller, array('family')) &&
1920                    in_array($currencyCode, Configure::read('family_plan.allowed_currencies')) &&                     
1921                    in_array($nativeLanguage, Configure::read('family_plan.allowed_languages'))
1922                ){
1923                    $confLanguage = $this->CountryCode->checkGlobalLanguage(array(
1924                        'language_code' => $nativeLanguage
1925                    ));
1926                }
1927                
1928                // set the language for translation
1929                if ($confLanguage) {
1930                    $this->Session->write('Config.language', $languageCodeIso2);
1931                } else {
1932                    $this->Session->write('Config.language', 'eng');
1933                }
1934
1935                
1936                // allow access for family plan pages for other languages
1937                if(
1938                    !in_array($controller, array('family')) &&
1939                    !in_array($currencyCode, Configure::read('family_plan.allowed_currencies'))
1940                ){
1941                    return $this->redirect(myTools::getUrl() . '/mobapp/region_restriction');
1942                }
1943            }
1944        } else {
1945            return $this->redirect('/mobapp/retrypage');
1946        }
1947    }
1948
1949    /* this will redirect to restriction page if language and currency not allowed
1950    * check language for non login user 
1951    */
1952    public function checkIfAllowed() {
1953        // disable foreign language if "la" is set
1954       if (isset($this->request->query['la'])) {
1955            $lang = $this->request->query['la'];
1956            if (!empty($lang) && $lang !== Configure::read('default.user_language')) {
1957                //set language
1958                $languageCodeIso2 = $this->CountryCode->convertLangIso(array(
1959                    'language_code' => $lang,
1960                    'target_iso' => 2
1961                ));
1962
1963                $confLanguage = $this->CountryCode->checkGlobalLanguage(array(
1964                    'language_code' => $lang,
1965                    'unset_language_code' => array('ja')
1966                ));
1967
1968                // set the language for translation
1969                if ($confLanguage) {
1970                    $this->Session->write('Config.language', $languageCodeIso2);
1971                } else {
1972                    $this->Session->write('Config.language', 'eng');
1973                }        
1974                return $this->redirect(myTools::getUrl() . '/mobapp/region_restriction');
1975            }
1976        }
1977        // if token is set check user currency
1978        if (isset($this->request->query['token'])) {
1979            $this->jpyOnlyPage();
1980        }
1981    }
1982
1983    /**
1984    * Set memcache timezone
1985    * @param int userId
1986    * @return array ['timezone_id']
1987    */
1988    public function getTimezoneData($userId = NULL) {
1989        $this->loadModel('Timezone');
1990        //initialize memcache
1991        $memcached = new myMemcached();
1992
1993        $timezone = array(
1994            'Timezone' => array(
1995                'id' => Configure::read('default.user_timezone_id'),
1996            )
1997        );
1998
1999        $defaultTimezoneName = Configure::read('default.timezone_name');
2000
2001        $timezoneName = empty($this->request->data['User']['timezone']) ? $defaultTimezoneName : $this->request->data['User']['timezone'];
2002        $tznArr = explode('/', $timezoneName);
2003
2004        //get continents
2005        $continents = array_flip(Configure::read('continents'));
2006
2007        // log and use user current timezone settings if user computer timezone format is incorrect
2008        if (
2009            !isset($tznArr[0]) ||
2010            (isset($tznArr[0]) && !isset($continents[$tznArr[0]]))
2011        ) {
2012            $this->log(__METHOD__ . ' Timezone value format is incorrect. -->' . json_encode($timezoneName) . ' | userId --> ' . json_encode($userId), 'debug');
2013            $userTimezone = NULL;
2014            if ($userId) {
2015                // get user current timezone used
2016                $userTimezone = $this->User->useReplica()->find('first', array(
2017                    'fields' => 'timezone_id',
2018                    'conditions' => array(
2019                        'id' => $userId,
2020                        'timezone_id is not null' 
2021                    ),
2022                    'recursive' => -1
2023                ));
2024            }
2025
2026            $timezoneName = $defaultTimezoneName;
2027            //Configure::read('default.user_timezone_id');
2028
2029            if ($userTimezone) {
2030                $timezoneList = $this->Timezone->getFormattedTimezones();
2031                $usertimezoneDetail = isset($timezoneList[$userTimezone['User']['timezone_id']]) ? $timezoneList[$userTimezone['User']['timezone_id']] : null;
2032
2033                if ($usertimezoneDetail) {
2034                    $timezone['Timezone']['id'] = $userTimezone['User']['timezone_id'];
2035                } else {
2036                    $this->log(__METHOD__ . ' Timezone is not exist in memcached timezone list. -->' . json_encode($userTimezone) . ' | userId --> ' . json_encode($userId), 'debug');
2037                }
2038            }
2039        } else {
2040            $timezone = $this->Timezone->updateTimezoneTable(array('timezoneName' => $timezoneName));
2041        }
2042
2043        if ($timezone) {
2044            $jpTimeDiffData = $this->Timezone->computeTimeDiff(array(
2045                'continent_id' => isset($timezone['Timezone']['continent_id']) ? $timezone['Timezone']['continent_id'] : NULL,
2046                'city' => isset($timezone['Timezone']['city_eng']) ? $timezone['Timezone']['city_eng'] : NULL
2047            ));
2048
2049            if (isset($jpTimeDiffData['success']) && $jpTimeDiffData['success']) {
2050                $this->timeDiff = $jpTimeDiffData['timeDiff'];
2051                $this->utcOffset = $jpTimeDiffData['utc'];
2052            
2053                //save to memcache 
2054                $memcached->set(array(
2055                    'key' => 'user-timediff-' . $userId,
2056                    'value' => array(
2057                        'timeDiff' => $this->timeDiff,
2058                        'utc' => $this->utcOffset
2059                    ),
2060                    'expire' => 604800 //1 week
2061                ));
2062            }
2063
2064            return array(
2065                'timezone_id' => !empty($timezone['Timezone']['id']) ? $timezone['Timezone']['id'] : NULL
2066            );
2067        }
2068
2069        return NULL;
2070    }
2071
2072    /**
2073    * Settle paypal payment receivables
2074    * @param array user data
2075    * @return boolean
2076    */
2077    protected function chargePayPalPaymentReceivable($params = array()) {
2078        //validate need data for payment receivable
2079        if (
2080            empty($params['id']) ||
2081            empty($params['email']) ||
2082            empty($params['currency_code']) ||
2083            empty($params['payment_plan_id']) ||
2084            empty($params['price_id']) ||
2085            empty($params['card_company']) ||
2086            empty($params['paypal_billing_agreement_id'])
2087        )
2088        {
2089            $this->log(__METHOD__ . "error data pass. Data : " . json_encode($params), 'debug');
2090            return false;
2091        }
2092
2093        $userId = $params['id'];
2094        $currencyCode = $params['currency_code'];
2095        $paymentPlanId = $params['payment_plan_id'];
2096        $priceId = $params['price_id'];
2097
2098        // set db connection
2099        $db = ConnectionManager::getDataSource('default');
2100        //db resources reconnect
2101        if ($db->isConnected()) {
2102            $db->close(); // stop
2103        }
2104        $db->reconnect();
2105
2106        $rawQuery = "SELECT 
2107                (SELECT 
2108                        SUM(`amount`) AS `amount`
2109                    FROM
2110                        `payment_receivables`
2111                    WHERE
2112                        `payment_receivables`.`user_id` = u.id
2113                            AND `payment_receivables`.`status` = 0
2114                            AND `payment_receivables`.`payment_element_type` = 1
2115                            AND `payment_receivables`.`created` <= NOW()) AS receivables,
2116                (SELECT 
2117                        SUM(`amount`) AS `amount`
2118                    FROM
2119                        `payment_receivables`
2120                    WHERE
2121                        `payment_receivables`.`user_id` = u.id
2122                            AND `payment_receivables`.`status` = 0
2123                            AND `payment_receivables`.`payment_element_type` = 2
2124                            AND `payment_receivables`.`created` <= NOW()) AS appreciation_receivables,
2125                (SELECT 
2126                        SUM(`amount`) AS `amount`
2127                    FROM
2128                        `payment_receivables`
2129                    WHERE
2130                        `payment_receivables`.`user_id` = u.id
2131                            AND `payment_receivables`.`status` = 0
2132                            AND `payment_receivables`.`payment_element_type` = 3
2133                            AND `payment_receivables`.`created` <= NOW()) AS live_receivables                        
2134            FROM  users AS u WHERE u.id = {$userId}
2135        ";
2136
2137        $result = $this->User->query($rawQuery);
2138
2139        $receivableAmount = isset( $result[0][0]['receivables'] ) && $result[0][0]['receivables'] ? $result[0][0]['receivables'] : 0 ;
2140        $appreciationReceivableAmount = isset( $result[0][0]['appreciation_receivables'] ) && $result[0][0]['appreciation_receivables'] ? $result[0][0]['appreciation_receivables'] : 0 ;
2141        $liveReceivableAmount = isset( $result[0][0]['live_receivables'] ) && $result[0][0]['live_receivables'] ? $result[0][0]['live_receivables'] : 0 ;
2142        $totalReceivableAmount = $receivableAmount + $appreciationReceivableAmount + $liveReceivableAmount;
2143
2144        // check payment receivable
2145        if ( $totalReceivableAmount < 1 ) {
2146            $this->log(__METHOD__ . "::No payment receivable. \n Data : " . json_encode($params), 'debug');
2147            return false;
2148        }
2149
2150        //generate ordd code
2151        $paymentHash = myTools::generateOrderCode($userId);
2152        $membershipStatusIndex = UserTable::getStudentMembershipStatus($userId);
2153        // Reservation payment transaction 
2154        if( $receivableAmount > 0 ) {
2155
2156            $paymentParams = array(
2157                'currencyCode' => $currencyCode,
2158                'formType' => Configure::read('payment_credit_receivable'),
2159                'paymentType' => Configure::read('payment_types.payment_receivable'),
2160                'logFileName' => 'debug',
2161                'paymentAmount' => $receivableAmount,
2162                'priceId' => $priceId,
2163                'paymentPlanId' => $paymentPlanId
2164            );
2165
2166            $ptParams = array(
2167                'user_id' => $userId,
2168                'payment_hash' => $paymentHash,
2169                'course_id' => Configure::read("credit.course_id"),
2170                'payment_params' => json_encode($paymentParams),
2171            );
2172
2173            // create payment transaction
2174            if (!$pt = $this->PaymentTransaction->setWPPaymentTransaction($ptParams)) {
2175                $this->log(__METHOD__ . "::Cannot create payment transaction. \nData:" .json_encode($ptParams), 'debug');
2176                return false;
2177            }
2178            
2179        }
2180        // Appreciation payment transaction
2181        if( $appreciationReceivableAmount > 0 ) {
2182
2183            $paymentParams = array(
2184                'currencyCode' => $currencyCode,
2185                'formType' => Configure::read('payment_credit_appreciation_receivable'),
2186                'paymentType' => Configure::read('payment_types.payment_receivable'),
2187                'logFileName' => 'debug',
2188                'paymentAmount' => $appreciationReceivableAmount,
2189                'priceId' => $priceId,
2190                'paymentPlanId' => $paymentPlanId
2191            );
2192
2193            $ptParams = array(
2194                'user_id' => $userId,
2195                'payment_hash' => $paymentHash,
2196                'course_id' => Configure::read("credit.course_id"),
2197                'payment_params' => json_encode($paymentParams),
2198            );
2199
2200            // create payment transaction
2201            if (!$apt = $this->PaymentTransaction->setWPPaymentTransaction($ptParams)) {
2202                $this->log(__METHOD__ . "::Cannot create payment transaction. \nData:" .json_encode($ptParams), 'debug');
2203                return false;
2204            }
2205
2206        }
2207
2208        // Live payment transaction
2209        if ($liveReceivableAmount > 0) {
2210
2211            $paymentParams = array(
2212                'currencyCode' => $currencyCode,
2213                'formType' => Configure::read('payment_live_lesson_receivable'),
2214                'paymentType' => Configure::read('payment_types.payment_receivable'),
2215                'logFileName' => 'debug',
2216                'paymentAmount' => $liveReceivableAmount,
2217                'priceId' => $priceId,
2218                'paymentPlanId' => $paymentPlanId
2219            );
2220
2221            $ptParams = array(
2222                'user_id' => $userId,
2223                'payment_hash' => $paymentHash,
2224                'course_id' => Configure::read("credit.course_id"),
2225                'payment_params' => json_encode($paymentParams),
2226            );
2227
2228            // create payment transaction
2229            if (!$lpt = $this->PaymentTransaction->setWPPaymentTransaction($ptParams)) {
2230                $this->log(__METHOD__ . "::Cannot create payment transaction. \nData:" .json_encode($ptParams), 'debug');
2231                return false;
2232            }
2233        }
2234
2235        //db resources reconnect
2236        if ($db->isConnected()) {
2237            $db->close(); // stop
2238        }
2239        $db->reconnect();
2240
2241        // load PayPal class
2242        if (!class_exists('PayPal')) {
2243            App::import('Lib', 'PayPal');
2244        }
2245
2246        $paypal = new PayPal();
2247
2248        // get access token data
2249        $accessTokenData = $paypal->getAccessToken();
2250
2251        // return if error
2252        if (isset($accessTokenData['error'])) {
2253            $this->log(__METHOD__ . ' error -->' . json_encode($accessTokenData) . "\n | params --> " . json_encode($params), 'debug');
2254            return false;
2255        }
2256
2257        $createOrderParams = array(
2258            'accessToken' => $accessTokenData['access_token'],
2259            'paypalRequestId' => (isset($pt['id']) && $pt['id']) ? $pt['id'] : (isset($apt['id']) ? $apt['id'] : $lpt['id']),
2260            'intent' => 'CAPTURE',
2261            'paymentHash' => $paymentHash,
2262            'userId' => $userId,
2263            'currencyCode' => $currencyCode,
2264            'amount' => (int)$totalReceivableAmount,
2265            'billingAgreementId' => $params['paypal_billing_agreement_id']
2266        );
2267
2268        // void authorization
2269        $orderResult = $paypal->createOrder($createOrderParams);
2270        $paymentSuccess = isset($orderResult['status']) && $orderResult['status'] == 'COMPLETED' ? true : false;
2271        $this->loadModel('Payment');
2272
2273        // Reservation payment
2274        if( $receivableAmount > 0 ) {
2275            $savePaymentArr = array(
2276                'user_id' => $userId,
2277                'type_id' => 2,
2278                'pay_kbn' => 1,
2279                'reference_id' => $userId,
2280                'payment_transaction_password' => $paymentSuccess ? $pt['password'] : '',
2281                'status' => $paymentSuccess ? 1 : '',
2282                'form_type' => Configure::read('payment_credit_receivable'),
2283                'ordd' => $paymentSuccess ? $paymentHash : '',
2284                'amount' => $receivableAmount,
2285                'param1' => json_encode($orderResult),
2286                'param2' => $paymentSuccess ? '' : 'error',
2287                'card_company' => Configure::read('card_company.paypal'),
2288                'transaction_code' => $paymentSuccess ? $paymentHash : '',
2289                'currency_id' => Configure::read('default.settlement_currency_id'),
2290                'currency_code' => $currencyCode,
2291                'payment_id' => $paymentPlanId,
2292                'price_id' => $priceId,
2293                'payment_type' => Configure::read('payment_types.payment_receivable'),
2294                'logFileName' => 'debug'
2295            );
2296
2297            // create new payment
2298            $paymentSave = $this->Payment->rawSavePayment($savePaymentArr);
2299        }
2300
2301        // Appreciation payment
2302        if( $appreciationReceivableAmount > 0 ) {
2303            $savePaymentArr = array(
2304                'user_id' => $userId,
2305                'type_id' => 2,
2306                'pay_kbn' => 1,
2307                'reference_id' => $userId,
2308                'payment_transaction_password' => $paymentSuccess ?($pt['password'] ?? ''): '',
2309                'status' => $paymentSuccess ? 1 : '',
2310                'form_type' => Configure::read('payment_credit_appreciation_receivable'),
2311                'ordd' => $paymentSuccess ? $paymentHash : '',
2312                'amount' => $appreciationReceivableAmount,
2313                'param1' => json_encode($orderResult),
2314                'param2' => $paymentSuccess ? '' : 'error',
2315                'card_company' => Configure::read('card_company.paypal'),
2316                'transaction_code' => $paymentSuccess ? $paymentHash : '',
2317                'currency_id' => Configure::read('default.settlement_currency_id'),
2318                'currency_code' => $currencyCode,
2319                'payment_id' => $paymentPlanId,
2320                'price_id' => $priceId,
2321                'payment_type' => Configure::read('payment_types.payment_receivable'),
2322                'logFileName' => 'debug'
2323            );
2324
2325            // create new payment
2326            $paymentSave = $this->Payment->rawSavePayment($savePaymentArr);
2327        }
2328
2329        // Live payment
2330        if( $liveReceivableAmount > 0 ) {
2331            $savePaymentArr = array(
2332                'user_id' => $userId,
2333                'type_id' => 2,
2334                'pay_kbn' => 1,
2335                'reference_id' => $userId,
2336                'payment_transaction_password' => $paymentSuccess ? ($pt['password'] ?? '') : '',
2337                'status' => $paymentSuccess ? 1 : '',
2338                'form_type' => Configure::read('payment_live_lesson_receivable'),
2339                'ordd' => $paymentSuccess ? $paymentHash : '',
2340                'amount' => $liveReceivableAmount,
2341                'param1' => json_encode($orderResult),
2342                'param2' => $paymentSuccess ? '' : 'error',
2343                'card_company' => Configure::read('card_company.paypal'),
2344                'transaction_code' => $paymentSuccess ? $paymentHash : '',
2345                'currency_id' => Configure::read('default.settlement_currency_id'),
2346                'currency_code' => $currencyCode,
2347                'payment_id' => $paymentPlanId,
2348                'price_id' => $priceId,
2349                'payment_type' => Configure::read('payment_types.payment_receivable'),
2350                'logFileName' => 'debug'
2351            );
2352
2353            // create new payment
2354            $paymentSave = $this->Payment->rawSavePayment($savePaymentArr);
2355        }        
2356
2357        if ($paymentSave && $paymentSuccess) {
2358
2359            // Update Reservation payment receivables
2360            if( $receivableAmount > 0 ) {
2361                // get payment id
2362                $paymentData = $this->Payment->find('first', array(
2363                    'fields' => array(),
2364                    'conditions' => array(
2365                        'user_id' => $userId,
2366                        'form_type' => Configure::read('payment_credit_receivable'),
2367                        'ordd' => $paymentHash
2368                    ),
2369                    'recursive' => -1
2370                ));
2371
2372                if ($paymentData) {
2373                    $this->loadModel('PaymentReceivable');
2374                    // set payment receivable statuses to 2 - received
2375                    $this->PaymentReceivable->updateReceivableReservationPayment(
2376                        $userId,
2377                        array(
2378                            'status' => 2,
2379                            'payment_id' => $paymentData['Payment']['id'],
2380                            'payment_collection_date' => date("Y-m-d H:i:s"),
2381                            'card_company' => Configure::read('card_company.paypal'),
2382                            'payment_plan_id' => $paymentPlanId,
2383                            'membership_type_index' => $membershipStatusIndex
2384                        ),
2385                        array(
2386                            'PaymentReceivable.user_id' => $userId,
2387                            'PaymentReceivable.status' => 0,
2388                            'PaymentReceivable.payment_element_type' => 1,
2389                            'PaymentReceivable.created <=' => date('Y-m-d H:i:s')
2390                        )
2391                    );
2392                }
2393            }
2394
2395            // Update Appreciation payment receivables
2396            if( $appreciationReceivableAmount > 0 ) {
2397                // get payment id
2398                $paymentData = $this->Payment->find('first', array(
2399                    'fields' => array(),
2400                    'conditions' => array(
2401                        'user_id' => $userId,
2402                        'form_type' => Configure::read('payment_credit_appreciation_receivable'),
2403                        'ordd' => $paymentHash
2404                    ),
2405                    'recursive' => -1
2406                ));
2407
2408                if ($paymentData) {
2409                    $this->loadModel('PaymentReceivable');
2410                    // set payment receivable statuses to 2 - received
2411                    $this->PaymentReceivable->updateReceivableReservationPayment(
2412                        $userId,
2413                        array(
2414                            'status' => 2,
2415                            'payment_id' => $paymentData['Payment']['id'],
2416                            'payment_collection_date' => date("Y-m-d H:i:s"),
2417                            'card_company' => Configure::read('card_company.paypal'),
2418                            'payment_plan_id' => $paymentPlanId,
2419                            'membership_type_index' => $membershipStatusIndex
2420                        ),
2421                        array(
2422                            'PaymentReceivable.user_id' => $userId,
2423                            'PaymentReceivable.status' => 0,
2424                            'PaymentReceivable.payment_element_type' => Configure::read('appreciation_data.payment_element_type'),
2425                            'PaymentReceivable.created <=' => date('Y-m-d H:i:s')
2426                        )
2427                    );
2428                }
2429            }
2430
2431            // Update live payment receivables
2432            if( $liveReceivableAmount > 0 ) {
2433                // get payment id
2434                $paymentData = $this->Payment->find('first', array(
2435                    'fields' => array(),
2436                    'conditions' => array(
2437                        'user_id' => $userId,
2438                        'form_type' => Configure::read('payment_live_lesson_receivable'),
2439                        'ordd' => $paymentHash
2440                    ),
2441                    'recursive' => -1
2442                ));
2443
2444                if ($paymentData) {
2445                    $this->loadModel('PaymentReceivable');
2446                    // set payment receivable statuses to 2 - received
2447                    $this->PaymentReceivable->updateReceivableReservationPayment(
2448                        $userId,
2449                        array(
2450                            'status' => 2,
2451                            'payment_id' => $paymentData['Payment']['id'],
2452                            'payment_collection_date' => date("Y-m-d H:i:s"),
2453                            'card_company' => Configure::read('card_company.paypal'),
2454                            'payment_plan_id' => $paymentPlanId,
2455                            'membership_type_index' => $membershipStatusIndex                            
2456                        ),
2457                        array(
2458                            'PaymentReceivable.user_id' => $userId,
2459                            'PaymentReceivable.status' => 0,
2460                            'PaymentReceivable.payment_element_type' => 3,
2461                            'PaymentReceivable.created <=' => date('Y-m-d H:i:s')
2462                        )
2463                    );
2464                }
2465            }            
2466
2467        }
2468        if( isset($pt['id']) ) {
2469            $ptUpdateParams = array(
2470                'id' => $pt['id'],
2471                'fields' => array(
2472                    'status' => $paymentSuccess ? 1 : 2,
2473                    'response_text' => $orderResult
2474                ),
2475                'logFileName' => 'debug'
2476            );
2477
2478            // update payment transaction
2479            if (!$this->PaymentTransaction->updateWPPaymentTransaction($ptUpdateParams)) {
2480                $this->log(__METHOD__ . ' Cannot update payment transaction. --> ' . json_encode($ptUpdateParams), 'debug');
2481            }
2482        }
2483
2484        if( isset($apt['id']) ) {
2485            $ptUpdateParams = array(
2486                'id' => $apt['id'],
2487                'fields' => array(
2488                    'status' => $paymentSuccess ? 1 : 2,
2489                    'response_text' => $orderResult
2490                ),
2491                'logFileName' => 'debug'
2492            );
2493            // update payment transaction
2494            if (!$this->PaymentTransaction->updateWPPaymentTransaction($ptUpdateParams)) {
2495                $this->log(__METHOD__ . ' Cannot update payment transaction. --> ' . json_encode($ptUpdateParams), 'debug');
2496            }
2497        }
2498
2499        if( isset($lpt['id']) ) {
2500            $ptUpdateParams = array(
2501                'id' => $lpt['id'],
2502                'fields' => array(
2503                    'status' => $paymentSuccess ? 1 : 2,
2504                    'response_text' => $orderResult
2505                ),
2506                'logFileName' => 'debug'
2507            );
2508            // update payment transaction
2509            if (!$this->PaymentTransaction->updateWPPaymentTransaction($ptUpdateParams)) {
2510                $this->log(__METHOD__ . ' Cannot update payment transaction. --> ' . json_encode($ptUpdateParams), 'debug');
2511            }
2512        }        
2513
2514        // log
2515        $this->log(__METHOD__ . "::PaymentReceivable charge on withdrawal. \nData: " . json_encode(array('params' => $params, 'result' => $orderResult)), 'debug');
2516    }
2517
2518    /**
2519    * Settle payment receivables 
2520    * @param array user data
2521    * @return boolean
2522    */
2523    protected function chargePaymentReceivable($params = array()) {
2524        //validate need data for payment receivable
2525        if (
2526            empty($params['id']) ||
2527            empty($params['email']) ||
2528            empty($params['currency_code']) ||
2529            empty($params['payment_plan_id']) ||
2530            empty($params['price_id']) ||
2531            empty($params['card_company']) 
2532        )
2533        {
2534            $this->log(__METHOD__ . "error data pass. Data : " . json_encode($params), 'debug');
2535            return false;
2536        }
2537
2538        $userId = $params['id'];
2539        $currencyCode = $params['currency_code'];
2540        $paymentPlanId = $params['payment_plan_id'];
2541        $priceId = $params['price_id'];
2542
2543        // set db connection
2544        $db = ConnectionManager::getDataSource('default');
2545        //db resources reconnect
2546        if ($db->isConnected()) {
2547            $db->close(); // stop
2548        }
2549        $db->reconnect();        
2550
2551        $rawQuery = "
2552            SELECT 
2553                SUM(`amount`) as `amount`
2554            FROM
2555                `payment_receivables`
2556            WHERE
2557                `payment_receivables`.`user_id` = {$userId}
2558                AND `payment_receivables`.`status` = 0
2559                AND `payment_receivables`.`payment_element_type` IN (1 , 2, 3)
2560                AND `payment_receivables`.`created` <= NOW();
2561        ";
2562        $result = $this->User->query($rawQuery);
2563
2564        //check payment receivable
2565        if (!isset($result[0][0]['amount']) || empty($result[0][0]['amount'])) {
2566            $this->log(__METHOD__ . "::No payment receivable. \n Data : " . json_encode($params), 'debug');
2567            return false;
2568        }
2569
2570        //get payment receivable
2571        $receivablePayment = $result[0][0]['amount'];        
2572
2573        //generate ordd code
2574        $paymentHash = myTools::generateOrderCode($userId);
2575        $familyId = null;
2576
2577        $paymentParams = array(
2578            'currencyCode' => $currencyCode,
2579            'formType' => Configure::read('payment_credit_receivable'),
2580            'paymentType' => Configure::read('payment_types.payment_receivable'),
2581            'logFileName' => 'debug',
2582            'paymentAmount' => $receivablePayment,
2583            'familyId' => $familyId,
2584            'priceId' => $priceId,
2585            'paymentPlanId' => $paymentPlanId
2586        );
2587
2588        // if corporate user
2589        if (isset($params['corporate_id'])) {
2590            $paymentParams['corporateSettlementType'] = Configure::read('corporate_settlement_types.receivable_reservation_payment');
2591        }
2592
2593        $ptParams = array(
2594            'userId' => $userId,
2595            'status' => 0,
2596            'paymentHash' => $paymentHash,
2597            'paymentParams' => json_encode($paymentParams),
2598            'responseText' => '',
2599            'logFileName' => 'debug'
2600        );
2601
2602        //db resources reconnect
2603        if ($db->isConnected()) {
2604            $db->close(); // stop
2605        }
2606        $db->reconnect();
2607
2608        // create payment transaction
2609        if (!$pt = $this->PaymentTransaction->rawSaveCronPaymentTransaction($ptParams)) {
2610            $this->log(__METHOD__ . "::Cannot create payment transaction. \nData:" .json_encode($ptParams), 'debug');
2611            return false;            
2612        }
2613
2614        //db resources reconnect
2615        if ($db->isConnected()) {
2616            $db->close(); // stop
2617        }
2618        $db->reconnect();
2619
2620        //default user data
2621        $clientIp = PaymentTable::getClientIpByCompanyId($params['card_company']);
2622        $email = $params['email'];
2623        $sendId = $params['id'];
2624
2625        //set payment data
2626        $params = array(
2627            'clientIp' => $clientIp,
2628            'email' => $email,
2629            'sendId' => $sendId,
2630            'money' => $receivablePayment,
2631            'paymentHash' => $paymentHash
2632        );    
2633
2634        $fallBackPayment = ZChargeComponent::charge_with_regsterd_card(json_encode($params));
2635
2636        // log
2637        $this->log(__METHOD__ . "::PaymentReceivable charge on withdrawal. \nData: " . json_encode(array('params' => $params, 'result' => $fallBackPayment)), 'debug');
2638    }
2639
2640    /**
2641    * Charge worlplay users on withdraw
2642    * @param array - user data
2643    * @return boolean
2644    */
2645    protected function wpChargePaymentReceivable($params = array()) {
2646        if (
2647            empty($params['id']) ||
2648            empty($params['email']) ||
2649            empty($params['currency_code']) ||
2650            empty($params['payment_plan_id']) ||
2651            empty($params['price_id']) ||
2652            empty($params['card_token'])
2653        ) {
2654            $this->log(__METHOD__ . "::Missing parameters. \nData : ". json_encode($params), 'debug');
2655            return false;
2656        }
2657
2658        // set db connection
2659        $db = ConnectionManager::getDataSource('default');
2660
2661        //db resources reconnect
2662        if ($db->isConnected()) {
2663            $db->close(); // stop
2664        }
2665        $db->reconnect();        
2666
2667        $userId = $params['id'];
2668
2669        $rawQuery = "SELECT 
2670                (SELECT 
2671                        SUM(`amount`) AS `amount`
2672                    FROM
2673                        `payment_receivables`
2674                    WHERE
2675                        `payment_receivables`.`user_id` = u.id
2676                            AND `payment_receivables`.`status` = 0
2677                            AND `payment_receivables`.`payment_element_type` in (1,2,3)
2678                            AND `payment_receivables`.`created` <= NOW()) AS receivables
2679            FROM  users AS u WHERE u.id = {$userId}
2680        ";
2681
2682        $result = $this->User->query($rawQuery);
2683
2684        $totalReceivableAmount = isset( $result[0][0]['receivables'] ) && $result[0][0]['receivables'] ? $result[0][0]['receivables'] : 0 ;
2685
2686        //check payment receivable
2687        if ( $totalReceivableAmount < 1 ) {
2688            $this->log(__METHOD__ . "::No payment receivable. \n Data : " . json_encode($params), 'debug');
2689            return false;
2690        }      
2691
2692        $email = $params['email'];
2693        $currencyCode = $params['currency_code'];
2694        $paymentPlanId = $params['payment_plan_id'];
2695        $priceId = $params['price_id'];
2696        $receivableFormType = Configure::read('payment_credit_receivable');
2697        $currencyExponents = Configure::read('worldpay.currency_exponents');
2698        $receivableOrderCode = myTools::generateOrderCode($userId);
2699        $paymentMethodType = myTools::getWPPaymentMethodType($params['card_brand'], 'payment');
2700        $merchantCode = myTools::getWPMerchantCode($paymentMethodType);
2701        $paymentMethod = explode('_', $paymentMethodType);
2702        $paymentMethod = isset($paymentMethod[0]) ? $paymentMethod[0] : null;
2703        $paymentPlanId = $paymentPlanId;
2704        $exponent = $currencyExponents[$currencyCode];
2705
2706        $receivablPaymentAmountArr = myTools::wpGetAmount($exponent, (float)$totalReceivableAmount);
2707        $ncAmount = $receivablPaymentAmountArr['ncAmount'];
2708        $wpAmount = $receivablPaymentAmountArr['wpAmount'];
2709        $membershipStatusIndex = UserTable::getStudentMembershipStatus($userId);
2710
2711        // Appreciation and Reservation payment transaction
2712        if( $totalReceivableAmount > 0 ) {
2713            $ptParams = array(
2714                'userId' => $userId,
2715                'status' => 0,
2716                'paymentHash' => $receivableOrderCode,
2717                'paymentParams' => json_encode(array(
2718                    'currencyCode' => $currencyCode,
2719                    'formType' => $receivableFormType,
2720                    'paymentType' => Configure::read('payment_types.payment_receivable'),
2721                    'logFileName' => 'debug',
2722                    'wpPaymentAmount' => $wpAmount,
2723                    'paymentAmount' => $ncAmount,
2724                    'cronDateRun' => $this->cronDateTime,
2725                    'priceId' => $priceId,
2726                    'paymentPlanId' => $paymentPlanId,
2727                    'merchantCode' => $merchantCode,
2728                    'membershipStatusIndex' => $membershipStatusIndex
2729                )),
2730                'responseText' => '',
2731                'logFileName' => 'debug'
2732            );
2733
2734            // create payment transaction
2735            if (!$pt = $this->PaymentTransaction->rawSaveCronPaymentTransaction($ptParams)) {
2736                $this->log(__METHOD__ . "::Cannot create payment transaction. \nData:" .json_encode($ptParams), 'debug');
2737                return false;
2738            }
2739        }
2740
2741        //set payment params
2742        $chargeParams = array(
2743            'merchantCode' => $merchantCode,
2744            'orderCode' => $receivableOrderCode,
2745            'description' => 'Payment Credit Receivable',
2746            'currencyCode' => $currencyCode,
2747            'exponent' => $exponent,
2748            'amount' => $wpAmount,
2749            'cardToken' => $params['card_token'],
2750            'email' => $email,
2751            'authenticatedShopperId' => $userId,
2752            'xmlName' => 'direct_payment_with_token',
2753            'shopperIpAddress' => '52.193.149.250', // ncweb6 server ip address
2754            'wpTransactionIdentifier' => $params['wp_transaction_identifier'],
2755            'paymentMethod' => $paymentMethod
2756        );        
2757
2758        $receivableResult = wpPaymentService::directPayment($chargeParams);
2759
2760        //check direct payment result
2761        if (!myTools::checkIfWPPaymentResponseIsAuthorised($receivableResult)) {
2762            $receivableStatus = 2; // error
2763        }
2764
2765        //db resources reconnect
2766        if ($db->isConnected()) {
2767            $db->close(); // stop
2768        }
2769        $db->reconnect();     
2770
2771        $this->PaymentTransaction->rawCronUpdatePaymentTransactionResponseTextAndStatus(array(
2772            'orderCode' => $receivableOrderCode,
2773            'responseText' => json_encode(array('cronMonthlyPaymentReceivable_response' => $receivableResult)),
2774            'status' => isset($receivableStatus) ? $receivableStatus : 2, // 1 - success, 2 - error
2775            'logFileName' => 'debug'
2776        ));
2777    }
2778
2779    public function setSeoLocalizeUrl() {
2780        $hasLocalizeSupport = true; // default
2781        $con = $this->params->params['controller'];
2782        $action = $this->params->params['action'];
2783
2784        // add controller and/or action for the web pages that will not be applied in the tags for SEO
2785        // if ($con == 'MyPage' && $action == 'index') { // --> this is just a sample
2786        //     $hasLocalizeSupport = false;
2787        // }
2788
2789        if (!$hasLocalizeSupport || $this->localizeDir == Configure::read('default.user_language')) {
2790            $seoLocalizeUrl = myTools::getUrl();
2791        } else {
2792            $seoLocalizeUrl = myTools::getUrl() . '/' . $this->localizeDir;
2793        }
2794
2795        $this->set('hasLocalizeSupport', $hasLocalizeSupport);
2796        $this->set('seoLocalizeUrl', $seoLocalizeUrl);
2797    }
2798
2799    /**
2800     * get currency code using user's currency code or local language directory currency code equivalent.
2801     */
2802    public function getCustomCurrencyCode() {
2803        return isset($this->sharedUserData['User']['currency_code']) ? $this->sharedUserData['User']['currency_code'] : (isset($this->localizeDir) && is_string($this->localizeDir) && isset($this->allowedCurrencies[$this->localizeDir]) ? $this->allowedCurrencies[$this->localizeDir] : Configure::read('default.user_currency'));
2804    }
2805
2806    /**
2807     * get premium plan price
2808     */
2809    public function getPremiumPlanPrice($params = []) {
2810        $logFileName = isset($params['logFileName']) ? $params['logFileName'] : null;
2811        $currencyCode = isset($params['currencyCode']) ? $params['currencyCode'] : null;
2812        $numberFormatFlg = isset($params['numberFormatFlg']) ? $params['numberFormatFlg'] : true;
2813        if (!isset($currencyCode)) {
2814            $currencyCode = $this->getCustomCurrencyCode();
2815        }
2816
2817
2818        $this->loadModel('PaymentPlanPrice');
2819        $amount = $this->PaymentPlanPrice->getMonthlyPrice(array(
2820            'currencyCode' => $currencyCode,
2821            'paymentPlanId' => Configure::read('payment_plans.premium_plan'),
2822            'numberFormatFlg' => $numberFormatFlg,
2823            'logFileName' => $logFileName
2824        ));
2825
2826        return $amount;
2827    }
2828
2829    /**
2830     * NC-7922: Stasapu cs admin domains not allowed access on user
2831    */
2832    private function checkStasapuDomain() {
2833        $env = Configure::read('ENVIRONMENT');
2834        $stasapuDomainArr = Configure::read('stasapucs_host');
2835        $getDomainArr = parse_url($_SERVER['HTTP_HOST']);
2836        $host = isset($getDomainArr['path']) ? $getDomainArr['path'] : null;
2837        if ( isset($stasapuDomainArr[$env]) && $host ) {
2838            if ( $host == $stasapuDomainArr[$env] ) {
2839                throw new NotFoundException();
2840            }
2841        }
2842    }
2843
2844    public function disablePageForSapuri($page='pc') {
2845        if ($page == 'pc' && $this->Auth->loggedIn() && $this->isStudySapuriUser) {
2846            return $this->isStudySapuriTosUser ? $this->redirect('/lesson-reservation') : $this->redirect('/mypage');
2847        }
2848
2849        if ($page == 'mobapp' && isset($this->request->query['token']) && $this->isStudySapuriUser) {
2850            // return $this->redirect('/mobapp/close?token='.$this->request->query['token']);
2851            return $this->redirect('/?plan=not_supported'.$this->request->query['token']);
2852        }
2853    }
2854    /**
2855     * block free user from sapuri toS student
2856     */
2857    public function blockWithdrawnSapuriToS($page = 'pc') {
2858        $token = !empty($this->request->query['token']) ? $this->request->query['token'] : null;
2859        $userId = null;
2860        $checkRes = [];
2861
2862        if ($page == 'mobapp' && $token) {
2863            $user = UserTable::validToken($token);
2864            $userId = isset($user['User']['id']) ? $user['User']['id'] : $userId;
2865        }
2866
2867        if ($page == 'pc' && $this->Auth->loggedIn()) {
2868            $userId = $this->Auth->user('id');
2869        }
2870
2871        if ($userId) {
2872            $usersExtend = ClassRegistry::init('UsersExtend');
2873            $usersExtend->openDBReplica();
2874            $checkRes = $usersExtend->find('first', [
2875                'conditions' => ['UsersExtend.user_id' => $userId]
2876            ]);
2877            $usersExtend->closeDBReplica();
2878        }
2879
2880        if (isset($checkRes) && count($checkRes)) {
2881            $redirectUrl = ($page == 'mobapp') ? '/mobapp/close?token='.$token : '/mypage';
2882            return $this->redirect($redirectUrl);
2883        }
2884    }
2885
2886    /**
2887     * NC-8916: create english hub cookie
2888    */
2889    private function createEnglishHubCookie() {
2890        $indexCookieStr = null;
2891        $p = "";
2892        $cid = "";
2893        
2894        // check cid and p params for ehub
2895        if ( 
2896                ( isset($this->request->query['cid']) && $this->request->query['cid'] ) && 
2897                ( isset($this->request->query['p']) && $this->request->query['p'] )
2898            )
2899        {
2900            $cid = $this->request->query['cid'];
2901            $p = $this->request->query['p'];
2902            
2903            // create index
2904            $indexCookieStr = "CL_".$p;
2905            $this->Cookie->write($indexCookieStr, $cid, false, Configure::read("cookieTime"));
2906        }
2907
2908        // check if campaign code for english hub is not set but english hub params are present
2909        if ( 
2910            // - if has index
2911            $indexCookieStr && 
2912            
2913            // - if current campaign_code is not from english hub
2914            ( 
2915                !$this->Cookie->check('campaign_code') || 
2916                
2917                // - has cookie data, but not enlish_hub cookie
2918                ( 
2919                    $this->Cookie->check('campaign_code') && 
2920                    $this->Cookie->read('campaign_code') != Configure::read("english_hub_affiliate_cc") 
2921                )
2922            )
2923            
2924            // - if from affee -> do not run campaign_code
2925            && $p != "phdiu0vd8jvm"
2926        ) {
2927            // create english hub cookie
2928            $this->Cookie->write('campaign_code',Configure::read("english_hub_affiliate_cc"), true, Configure::read("cookieTime") );
2929        }
2930        
2931        return $indexCookieStr;
2932    }
2933
2934    public function checkControllerActionExist($controller, $action) {
2935        $controller = Inflector::camelize($controller);
2936        $m_controller = $controller.'Controller';
2937        App::import('Controller', $m_controller);
2938
2939        if (!class_exists($m_controller)) return false;
2940
2941        $aMethods = get_class_methods($m_controller);
2942        if ($aMethods) {
2943            foreach ($aMethods as $idx => $method) {
2944                if($action==$method) return true;
2945            }
2946        } else  {
2947            //this is probably NOT a controller!
2948        }
2949        return false;
2950    }
2951
2952    /**
2953     * NC-9586: check if from SNS share
2954    */
2955    public function checkIfSNSShare(){
2956        if(
2957            isset($_GET["nc_share_ref"]) &&
2958            $_GET["nc_share_ref"] == "nc_sns_share" &&
2959            isset($_SERVER["HTTP_USER_AGENT"]) && 
2960            (
2961                (strpos($_SERVER["HTTP_USER_AGENT"], 'facebookexternalhit') !== false) ||
2962                (strpos($_SERVER["HTTP_USER_AGENT"], 'Twitterbot') !== false) ||
2963                (strpos($_SERVER["HTTP_USER_AGENT"], 'line-poker') !== false)
2964            )
2965        ){
2966            return true;
2967        }
2968
2969        return false;
2970    }
2971
2972
2973    /**
2974    * fetch user's appreciation options data for modal display
2975    * @param : array( 'chat_hash' => str )
2976    * @return : array( 'html_element' => str[html element] )
2977    */
2978    public function setUpAppreciationSelectionModalElement( $params = array() ) {
2979        $result = array();
2980        $chatHash = isset($params['chat_hash']) && $params['chat_hash'] ? $params['chat_hash'] : null ;
2981        if ( $chatHash ) {
2982
2983            $fetchAppreciationData = $this->LessonOnairsLog->fetchAppreciationOptionToTeacher(array( 'chat_hash' => $chatHash));
2984            if( 
2985                (isset($fetchAppreciationData['data']) && $fetchAppreciationData['data']) && 
2986                (
2987                    (isset($fetchAppreciationData['user_tips_appreciation_flg']) && $fetchAppreciationData['user_tips_appreciation_flg'] == 1) ||
2988                    (isset($fetchAppreciationData['user_message_appreciation_flg']) && $fetchAppreciationData['user_message_appreciation_flg'] == 1)
2989                )
2990            ) { // check data option available user_appreciation_flg
2991                $appreciationGroupAmountLogDataArr = $fetchAppreciationData['data'];
2992                $teacherteacherDataObj= new TeacherTable($fetchAppreciationData['teacher_data']);
2993
2994                // set default details var, normal teacher
2995                $_name = $teacherteacherDataObj->name;
2996                $_jp_name = $teacherteacherDataObj->jp_name;
2997                $_image_url = $teacherteacherDataObj->getImageUrl();
2998
2999                // if counselor teacher, set details var for counselor
3000                if(isset($teacherteacherDataObj->counseling_flg) && $teacherteacherDataObj->counseling_flg){
3001                    // get counselor default img
3002                    $counselorImageUrl = $teacherteacherDataObj->getProfileImage(Configure::read('default_counselor_detail'));
3003
3004                    // counselor data
3005                    $_name = 'Counselor';
3006                    $_jp_name = 'カウンセラー';
3007                    $_image_url = $counselorImageUrl['image_url'];
3008                }
3009
3010                // if avatar teacher, set details var for avatar parent
3011                if (
3012                    (isset($teacherteacherDataObj->avatar_id) && $teacherteacherDataObj->avatar_id) && 
3013                    (isset($teacherteacherDataObj->avatar_flg) && $teacherteacherDataObj->avatar_flg)
3014                ) {
3015                    // avatar parent data
3016                    $_name = $teacherteacherDataObj->getAvatarParentNameEn();
3017                    $_jp_name =  $teacherteacherDataObj->getAvatarParentName();
3018                    $_image_url = $teacherteacherDataObj->getAvatarParentImageUrl();
3019                }
3020
3021                // set teacher data for view
3022                $teacherData = array(
3023                    'id' => $teacherteacherDataObj->id,
3024                    'name' => $_name,
3025                    'jp_name' => $_jp_name,
3026                    'image_url' => $_image_url
3027                );
3028
3029                // - user data obj
3030                $userData = new UserTable($this->sharedUserData['User']);
3031
3032                // - user appreciation message/tips behavior NJ-53624
3033                $getTeacherCoinBoxData = $this->TeacherCoinBox->isHashExists($params['chat_hash'], $this->Auth->user('id'));
3034                $element_message = '';
3035                $tipShow = $fetchAppreciationData['user_tips_appreciation_flg'];
3036                $has_no_tips_yet = 1;
3037                if (!empty($getTeacherCoinBoxData)){
3038                    $element_message = $getTeacherCoinBoxData['TeacherCoinBox']['element_message'];
3039                    $has_no_tips_yet = $getTeacherCoinBoxData['TeacherCoinBox']['has_tips'] == 1 ? 0 : 1;
3040                }
3041                $finalTipShow = $tipShow == 1 ? $has_no_tips_yet : $tipShow;
3042                $view = new View($this, false);
3043                $appreciation_selection_modal_params = array(
3044                    'element_message' => $element_message,
3045                    'optionArr' => $appreciationGroupAmountLogDataArr,
3046                    'teacherArr' => $teacherData,
3047                    'chat_hash' => $chatHash,
3048                    'user_tips_appreciation_flg' => $finalTipShow,
3049                    'user_message_appreciation_flg' => $fetchAppreciationData['user_message_appreciation_flg'],
3050                    'card_company' => $this->sharedUserData['User']['card_company'],
3051                    'usersPointDetail' => $fetchAppreciationData['user_purchase_coin'] //NJ-12246: Get usersPointData
3052                );
3053
3054                //- NJ-23781 : get individual card flg if corporate users (card and bank transfer)
3055                if(in_array($userData->getMembershipTypeIndex(), Configure::read('corp_personal_card_payment_valid_memberships'))){
3056                    $getICFFlg = $this->UsersDetail->getCorpIndividualCardFlg(['user_id' => $this->Auth->user('id')]);
3057                    if($getICFFlg){
3058                        $appreciation_selection_modal_params['corp_individual_card_fail_flg'] = $getICFFlg['individual_card_fail_flg'];
3059                    }
3060                }
3061                if (
3062                    isset($fetchAppreciationData['user_message_appreciation_flg']) && $fetchAppreciationData['user_message_appreciation_flg'] == 1
3063                    ||
3064                    $finalTipShow == 1
3065                ){
3066                    $result['html_element'] = $view->element('appreciation_selection_modal', $appreciation_selection_modal_params);
3067                }
3068            }
3069
3070        }
3071        return $result;
3072    }
3073    /**
3074    * Send teacher's appreciation
3075    * @param : array( 'appreciation_id' => int, 'message' => str, 'chat_hash' => str )
3076    * @return : bool
3077    */
3078    public function sendTeacherAppreciation( $params = array() ) {
3079        $result = array( 'result' => 0 ); // false 
3080        $appreciationId = isset( $params['appreciation_id'] ) ? $params['appreciation_id'] : null; 
3081        $tipCoin = isset( $params['tip_coin'] ) ? $params['tip_coin'] : null;
3082        $message = isset( $params['message'] ) && $params['message'] ? $params['message'] : null; 
3083        $chathash = isset( $params['chat_hash'] ) && $params['chat_hash'] ? $params['chat_hash'] : null; 
3084        $action_mode = isset( $params['action_mode'] ) ? $params['action_mode'] : 0; 
3085
3086        $userData = $this->sharedUserData;
3087        $userID = $userData['User']['id'];
3088
3089        //fetch the show appreciation flg;show_appreciation_flg
3090        $userData = $this->User->find("first",array(
3091            'fields' => array(
3092                "User.show_appreciation_flg",
3093                "User.display_appreciation_message_flg"
3094            ),
3095            'conditions' => array(
3096                'User.id' => $userID
3097            )
3098        ));
3099
3100        $userData = $userData['User'] ?? array();
3101        $showAppreciationFlg = $userData['show_appreciation_flg'] ?? 0;
3102
3103        $showAppreciationMessageFlg = $userData['display_appreciation_message_flg'] ?? 0;
3104
3105        $sendParam = array(
3106            'chat_hash'  => $chathash,
3107            'appreciation_id'  => $appreciationId,
3108            'tip_coin'  => $tipCoin,
3109            'message' => $message,
3110            'access_point' => 'pc',
3111            'action_mode' => $action_mode
3112        );
3113
3114        //send the appreciation to teacher if flag is 1 
3115        if ((int)$showAppreciationFlg == 1 || (int)$showAppreciationMessageFlg == 1) {
3116            $sendData = $this->LessonOnairsLog->sendAppreciationToTeacher($sendParam);
3117            if ( isset ($sendData['result'] ) && $sendData['result'] ) {
3118                // set default res
3119                $result = array( 'result' => 1 );
3120
3121                // set return appreciation item
3122                $result['appreciation_details'] = $sendData['appreciation_item'];
3123
3124            } else {
3125                if( isset ($sendData['error'] ) && $sendData['error'] ){
3126                    $result['error']['id'] = 'sending_failed';
3127                    $result['error']['message'] = json_encode($sendData['error']);
3128                }
3129            }
3130        }else{
3131            $result['error']['id'] = 'show_flag_invalid';
3132            $result['error']['message'] = "Appreciation Show Flag is invalid, flag must be set to 'On' on the account settings";
3133        }
3134
3135        return $result;
3136    }
3137
3138    public function isLocalizeDirValid($code) {
3139
3140        $this->CountryCode->openDBReplica();
3141
3142        $result = $this->CountryCode->find('count', array(
3143            'conditions' => array('CountryCode.iso_639_1' => $code),
3144            'recursive' => -1
3145        ));
3146
3147        $this->CountryCode->closeDBReplica();
3148
3149        return $result;
3150    }
3151
3152    /**
3153    * Settle aftee payment receivables
3154    * @param array user data
3155    * @return boolean
3156    */
3157    protected function chargeAfteePaymentReceivable($params = array()) {
3158        //validate need data for payment receivable
3159        if (
3160            empty($params['id']) ||
3161            empty($params['email']) ||
3162            empty($params['currency_code']) ||
3163            empty($params['payment_plan_id']) ||
3164            empty($params['price_id']) ||
3165            empty($params['card_company'])
3166        )
3167        {
3168            $this->log(__METHOD__ . "error data pass. Data : " . json_encode($params), 'debug');
3169            return false;
3170        }
3171
3172        $userId = $params['id'];
3173        $currencyCode = $params['currency_code'];
3174        $paymentPlanId = $params['payment_plan_id'];
3175        $priceId = $params['price_id'];
3176
3177        // set db connection
3178        $db = ConnectionManager::getDataSource('default');
3179        //db resources reconnect
3180        if ($db->isConnected()) {
3181            $db->close(); // stop
3182        }
3183        $db->reconnect();
3184
3185        $rawQuery = "SELECT 
3186                (SELECT 
3187                        SUM(`amount`) AS `amount`
3188                    FROM
3189                        `payment_receivables`
3190                    WHERE
3191                        `payment_receivables`.`user_id` = u.id
3192                            AND `payment_receivables`.`status` = 0
3193                            AND `payment_receivables`.`payment_element_type` = 1
3194                            AND `payment_receivables`.`created` <= NOW()) AS receivables,
3195                (SELECT 
3196                        SUM(`amount`) AS `amount`
3197                    FROM
3198                        `payment_receivables`
3199                    WHERE
3200                        `payment_receivables`.`user_id` = u.id
3201                            AND `payment_receivables`.`status` = 0
3202                            AND `payment_receivables`.`payment_element_type` = 2
3203                            AND `payment_receivables`.`created` <= NOW()) AS appreciation_receivables,
3204                (SELECT 
3205                        SUM(`amount`) AS `amount`
3206                    FROM
3207                        `payment_receivables`
3208                    WHERE
3209                        `payment_receivables`.`user_id` = u.id
3210                            AND `payment_receivables`.`status` = 0
3211                            AND `payment_receivables`.`payment_element_type` = 3
3212                            AND `payment_receivables`.`created` <= NOW()) AS live_receivables                        
3213            FROM  users AS u WHERE u.id = {$userId}
3214        ";
3215
3216        $result = $this->User->query($rawQuery);
3217
3218        $receivableAmount = isset( $result[0][0]['receivables'] ) && $result[0][0]['receivables'] ? $result[0][0]['receivables'] : 0 ;
3219        $appreciationReceivableAmount = isset( $result[0][0]['appreciation_receivables'] ) && $result[0][0]['appreciation_receivables'] ? $result[0][0]['appreciation_receivables'] : 0 ;
3220        $liveReceivableAmount = isset( $result[0][0]['live_receivables'] ) && $result[0][0]['live_receivables'] ? $result[0][0]['live_receivables'] : 0 ;
3221        $totalReceivableAmount = $receivableAmount + $appreciationReceivableAmount + $liveReceivableAmount;
3222
3223        // check payment receivable
3224        if ( $totalReceivableAmount < 1 ) {
3225            $this->log(__METHOD__ . "::No payment receivable. \n Data : " . json_encode($params), 'debug');
3226            return false;
3227        }
3228
3229        //generate ordd code
3230        $paymentHash = myTools::generateOrderCode($userId);
3231        $membershipStatusIndex = UserTable::getStudentMembershipStatus($userId);
3232        // Reservation payment transaction 
3233        if( $receivableAmount > 0 ) {
3234
3235            $paymentParams = array(
3236                'currencyCode' => $currencyCode,
3237                'formType' => Configure::read('payment_credit_receivable'),
3238                'paymentType' => Configure::read('payment_types.payment_receivable'),
3239                'logFileName' => 'debug',
3240                'paymentAmount' => $receivableAmount,
3241                'priceId' => $priceId,
3242                'paymentPlanId' => $paymentPlanId
3243            );
3244
3245            $ptParams = array(
3246                'user_id' => $userId,
3247                'payment_hash' => $paymentHash,
3248                'course_id' => Configure::read("credit.course_id"),
3249                'payment_params' => json_encode($paymentParams),
3250            );
3251
3252            // create payment transaction
3253            if (!$pt = $this->PaymentTransaction->setWPPaymentTransaction($ptParams)) {
3254                $this->log(__METHOD__ . "::Cannot create payment transaction. \nData:" .json_encode($ptParams), 'debug');
3255                return false;
3256            }
3257            
3258        }
3259        // Appreciation payment transaction
3260        if( $appreciationReceivableAmount > 0 ) {
3261
3262            $paymentParams = array(
3263                'currencyCode' => $currencyCode,
3264                'formType' => Configure::read('payment_credit_appreciation_receivable'),
3265                'paymentType' => Configure::read('payment_types.payment_receivable'),
3266                'logFileName' => 'debug',
3267                'paymentAmount' => $appreciationReceivableAmount,
3268                'priceId' => $priceId,
3269                'paymentPlanId' => $paymentPlanId
3270            );
3271
3272            $ptParams = array(
3273                'user_id' => $userId,
3274                'payment_hash' => $paymentHash,
3275                'course_id' => Configure::read("credit.course_id"),
3276                'payment_params' => json_encode($paymentParams),
3277            );
3278
3279            // create payment transaction
3280            if (!$apt = $this->PaymentTransaction->setWPPaymentTransaction($ptParams)) {
3281                $this->log(__METHOD__ . "::Cannot create payment transaction. \nData:" .json_encode($ptParams), 'debug');
3282                return false;
3283            }
3284
3285        }
3286
3287        // Live payment transaction
3288        if ($liveReceivableAmount > 0) {
3289
3290            $paymentParams = array(
3291                'currencyCode' => $currencyCode,
3292                'formType' => Configure::read('payment_live_lesson_receivable'),
3293                'paymentType' => Configure::read('payment_types.payment_receivable'),
3294                'logFileName' => 'debug',
3295                'paymentAmount' => $liveReceivableAmount,
3296                'priceId' => $priceId,
3297                'paymentPlanId' => $paymentPlanId
3298            );
3299
3300            $ptParams = array(
3301                'user_id' => $userId,
3302                'payment_hash' => $paymentHash,
3303                'course_id' => Configure::read("credit.course_id"),
3304                'payment_params' => json_encode($paymentParams),
3305            );
3306
3307            // create payment transaction
3308            if (!$lpt = $this->PaymentTransaction->setWPPaymentTransaction($ptParams)) {
3309                $this->log(__METHOD__ . "::Cannot create payment transaction. \nData:" .json_encode($ptParams), 'debug');
3310                return false;
3311            }
3312        }
3313
3314        //db resources reconnect
3315        if ($db->isConnected()) {
3316            $db->close(); // stop
3317        }
3318        $db->reconnect();
3319
3320        // load PayPal class
3321        if (!class_exists('AfteePaymentService')) {
3322            App::import('Lib', 'AfteePaymentService');
3323        }
3324
3325        $afteeChecksumData = array(
3326            'shopItemId' => "AFTEE" . Configure::read('payment_credit_receivable'),
3327            'itemName' => 'PaymentReceivables',
3328            'itemPrice' => (int)$totalReceivableAmount,
3329            'itemCount' => 1,
3330            'customerPhoneNumber' => $params['phone_number'],
3331            'customerEmail' => $params['email'],
3332            'shopTransactionNo' => $paymentHash,
3333            'userID' => $userId
3334        );
3335        $afteeService = new AfteePaymentService();
3336        $checksum = $afteeService->generateChecksum($afteeChecksumData, false);
3337        
3338
3339        $afteeData = array(
3340            'authentication_token' => $params['card_token'],
3341            'related_id' => $params['aftee_transaction_identifier'],
3342            'checksum' => $checksum['checksum'],
3343            'shop_transaction_no' => $paymentHash,
3344            'transaction_options' => array(1)
3345        );
3346
3347        $afteePaymentData = array_merge($afteeData, $checksum['settlementData']);
3348
3349        // process Aftee direct payment
3350        $res = $afteeService->directPayment($afteePaymentData);
3351        $checkRes = json_decode($res, true);
3352        $orderResult = $res;
3353
3354        if ( isset($checkRes['object']) && $checkRes['object'] == 'transaction') {
3355            $paymentSuccess = true;
3356        } else if ( !array_key_exists("object", $checkRes) || (isset($checkRes['object']) && $checkRes['object'] == 'error')) {
3357            $paymentSuccess = false;
3358        }
3359
3360        $this->loadModel('Payment');
3361
3362        // Reservation payment
3363        if( $receivableAmount > 0 ) {
3364            $savePaymentArr = array(
3365                'user_id' => $userId,
3366                'type_id' => 2,
3367                'pay_kbn' => 1,
3368                'reference_id' => $userId,
3369                'payment_transaction_password' => $paymentSuccess ? $pt['password'] : '',
3370                'status' => $paymentSuccess ? 1 : '',
3371                'form_type' => Configure::read('payment_credit_receivable'),
3372                'ordd' => $paymentSuccess ? $paymentHash : '',
3373                'amount' => $receivableAmount,
3374                'param1' => $res,
3375                'param2' => $paymentSuccess ? '' : 'error',
3376                'card_company' => Configure::read('card_company.aftee'),
3377                'transaction_code' => $paymentSuccess ? $paymentHash : '',
3378                'currency_id' => Configure::read('default.settlement_currency_id'),
3379                'currency_code' => $currencyCode,
3380                'payment_id' => $paymentPlanId,
3381                'price_id' => $priceId,
3382                'payment_type' => Configure::read('payment_types.payment_receivable'),
3383                'logFileName' => 'debug'
3384            );
3385
3386            // create new payment
3387            $paymentSave = $this->Payment->rawSavePayment($savePaymentArr);
3388        }
3389
3390        // Appreciation payment
3391        if( $appreciationReceivableAmount > 0 ) {
3392            $savePaymentArr = array(
3393                'user_id' => $userId,
3394                'type_id' => 2,
3395                'pay_kbn' => 1,
3396                'reference_id' => $userId,
3397                'payment_transaction_password' => $paymentSuccess ? $pt['password'] : '',
3398                'status' => $paymentSuccess ? 1 : '',
3399                'form_type' => Configure::read('payment_credit_appreciation_receivable'),
3400                'ordd' => $paymentSuccess ? $paymentHash : '',
3401                'amount' => $appreciationReceivableAmount,
3402                'param1' => $res,
3403                'param2' => $paymentSuccess ? '' : 'error',
3404                'card_company' => Configure::read('card_company.aftee'),
3405                'transaction_code' => $paymentSuccess ? $paymentHash : '',
3406                'currency_id' => Configure::read('default.settlement_currency_id'),
3407                'currency_code' => $currencyCode,
3408                'payment_id' => $paymentPlanId,
3409                'price_id' => $priceId,
3410                'payment_type' => Configure::read('payment_types.payment_receivable'),
3411                'logFileName' => 'debug'
3412            );
3413
3414            // create new payment
3415            $paymentSave = $this->Payment->rawSavePayment($savePaymentArr);
3416        }
3417
3418        // Live payment
3419        if( $liveReceivableAmount > 0 ) {
3420            $savePaymentArr = array(
3421                'user_id' => $userId,
3422                'type_id' => 2,
3423                'pay_kbn' => 1,
3424                'reference_id' => $userId,
3425                'payment_transaction_password' => $paymentSuccess ? $pt['password'] : '',
3426                'status' => $paymentSuccess ? 1 : '',
3427                'form_type' => Configure::read('payment_live_lesson_receivable'),
3428                'ordd' => $paymentSuccess ? $paymentHash : '',
3429                'amount' => $liveReceivableAmount,
3430                'param1' => $res,
3431                'param2' => $paymentSuccess ? '' : 'error',
3432                'card_company' => Configure::read('card_company.aftee'),
3433                'transaction_code' => $paymentSuccess ? $paymentHash : '',
3434                'currency_id' => Configure::read('default.settlement_currency_id'),
3435                'currency_code' => $currencyCode,
3436                'payment_id' => $paymentPlanId,
3437                'price_id' => $priceId,
3438                'payment_type' => Configure::read('payment_types.payment_receivable'),
3439                'logFileName' => 'debug'
3440            );
3441
3442            // create new payment
3443            $paymentSave = $this->Payment->rawSavePayment($savePaymentArr);
3444        }        
3445
3446        if ($paymentSave && $paymentSuccess) {
3447
3448            // Update Reservation payment receivables
3449            if( $receivableAmount > 0 ) {
3450                // get payment id
3451                $paymentData = $this->Payment->find('first', array(
3452                    'fields' => array(),
3453                    'conditions' => array(
3454                        'user_id' => $userId,
3455                        'form_type' => Configure::read('payment_credit_receivable'),
3456                        'ordd' => $paymentHash
3457                    ),
3458                    'recursive' => -1
3459                ));
3460
3461                if ($paymentData) {
3462                    $this->loadModel('PaymentReceivable');
3463                    // set payment receivable statuses to 2 - received
3464                    $this->PaymentReceivable->updateReceivableReservationPayment(
3465                        $userId,
3466                        array(
3467                            'status' => 2,
3468                            'payment_id' => $paymentData['Payment']['id'],
3469                            'payment_collection_date' => date("Y-m-d H:i:s"),
3470                            'card_company' => Configure::read('card_company.aftee'),
3471                            'payment_plan_id' => $paymentPlanId,
3472                            'membership_type_index' => $membershipStatusIndex
3473                        ),
3474                        array(
3475                            'PaymentReceivable.user_id' => $userId,
3476                            'PaymentReceivable.status' => 0,
3477                            'PaymentReceivable.payment_element_type' => 1,
3478                            'PaymentReceivable.created <=' => date('Y-m-d H:i:s')
3479                        )
3480                    );
3481                }
3482            }
3483
3484            // Update Appreciation payment receivables
3485            if( $appreciationReceivableAmount > 0 ) {
3486                // get payment id
3487                $paymentData = $this->Payment->find('first', array(
3488                    'fields' => array(),
3489                    'conditions' => array(
3490                        'user_id' => $userId,
3491                        'form_type' => Configure::read('payment_credit_appreciation_receivable'),
3492                        'ordd' => $paymentHash
3493                    ),
3494                    'recursive' => -1
3495                ));
3496
3497                if ($paymentData) {
3498                    $this->loadModel('PaymentReceivable');
3499                    // set payment receivable statuses to 2 - received
3500                    $this->PaymentReceivable->updateReceivableReservationPayment(
3501                        $userId,
3502                        array(
3503                            'status' => 2,
3504                            'payment_id' => $paymentData['Payment']['id'],
3505                            'payment_collection_date' => date("Y-m-d H:i:s"),
3506                            'card_company' => Configure::read('card_company.aftee'),
3507                            'payment_plan_id' => $paymentPlanId,
3508                            'membership_type_index' => $membershipStatusIndex
3509                        ),
3510                        array(
3511                            'PaymentReceivable.user_id' => $userId,
3512                            'PaymentReceivable.status' => 0,
3513                            'PaymentReceivable.payment_element_type' => Configure::read('appreciation_data.payment_element_type'),
3514                            'PaymentReceivable.created <=' => date('Y-m-d H:i:s')
3515                        )
3516                    );
3517                }
3518            }
3519
3520            // Update live payment receivables
3521            if( $liveReceivableAmount > 0 ) {
3522                // get payment id
3523                $paymentData = $this->Payment->find('first', array(
3524                    'fields' => array(),
3525                    'conditions' => array(
3526                        'user_id' => $userId,
3527                        'form_type' => Configure::read('payment_live_lesson_receivable'),
3528                        'ordd' => $paymentHash
3529                    ),
3530                    'recursive' => -1
3531                ));
3532
3533                if ($paymentData) {
3534                    $this->loadModel('PaymentReceivable');
3535                    // set payment receivable statuses to 2 - received
3536                    $this->PaymentReceivable->updateReceivableReservationPayment(
3537                        $userId,
3538                        array(
3539                            'status' => 2,
3540                            'payment_id' => $paymentData['Payment']['id'],
3541                            'payment_collection_date' => date("Y-m-d H:i:s"),
3542                            'card_company' => Configure::read('card_company.aftee'),
3543                            'payment_plan_id' => $paymentPlanId,
3544                            'membership_type_index' => $membershipStatusIndex                            
3545                        ),
3546                        array(
3547                            'PaymentReceivable.user_id' => $userId,
3548                            'PaymentReceivable.status' => 0,
3549                            'PaymentReceivable.payment_element_type' => 3,
3550                            'PaymentReceivable.created <=' => date('Y-m-d H:i:s')
3551                        )
3552                    );
3553                }
3554            }            
3555
3556        }
3557        if( isset($pt['id']) ) {
3558            $ptUpdateParams = array(
3559                'id' => $pt['id'],
3560                'fields' => array(
3561                    'status' => $paymentSuccess ? 1 : 2,
3562                    'response_text' => array('aftee_directPayment_response' => $orderResult)
3563                ),
3564                'logFileName' => 'debug'
3565            );
3566
3567            // update payment transaction
3568            if (!$this->PaymentTransaction->updateAfteePaymentTransaction($ptUpdateParams)) {
3569                $this->log(__METHOD__ . ' Cannot update payment transaction. --> ' . json_encode($ptUpdateParams), 'debug');
3570            }
3571        }
3572
3573        if( isset($apt['id']) ) {
3574            $ptUpdateParams = array(
3575                'id' => $apt['id'],
3576                'fields' => array(
3577                    'status' => $paymentSuccess ? 1 : 2,
3578                    'response_text' => array('aftee_directPayment_response' => $orderResult)
3579                ),
3580                'logFileName' => 'debug'
3581            );
3582            // update payment transaction
3583            if (!$this->PaymentTransaction->updateAfteePaymentTransaction($ptUpdateParams)) {
3584                $this->log(__METHOD__ . ' Cannot update payment transaction. --> ' . json_encode($ptUpdateParams), 'debug');
3585            }
3586        }
3587
3588        if( isset($lpt['id']) ) {
3589            $ptUpdateParams = array(
3590                'id' => $lpt['id'],
3591                'fields' => array(
3592                    'status' => $paymentSuccess ? 1 : 2,
3593                    'response_text' => array('aftee_directPayment_response' => $orderResult)
3594                ),
3595                'logFileName' => 'debug'
3596            );
3597            // update payment transaction
3598            if (!$this->PaymentTransaction->updateAfteePaymentTransaction($ptUpdateParams)) {
3599                $this->log(__METHOD__ . ' Cannot update payment transaction. --> ' . json_encode($ptUpdateParams), 'debug');
3600            }
3601        }        
3602
3603        // log
3604        $this->log(__METHOD__ . "::PaymentReceivable charge on withdrawal. \nData: " . json_encode(array('params' => $params, 'result' => $orderResult)), 'debug');
3605    }
3606
3607    /**
3608     * Aftee Payment method
3609     * Check if aftee should be enabled/disabled in app
3610     */
3611    public function checkAfteeSupported($userData,$pcFlag = false) {
3612        $afteeAppSupportedVersion = Configure::read('aftee_app_version_support');
3613        $appVersion = isset($this->request->query['appVersion']) && !empty($this->request->query['appVersion']) ? $this->request->query['appVersion'] : 0;
3614        $deviceType = isset($this->request->query['deviceType']) && !empty($this->request->query['deviceType']) ? $this->request->query['deviceType'] : 0;
3615
3616        // initial values
3617        $isAfteeUser = isset($this->isAfteeUser) ? $this->isAfteeUser : 0;
3618        $enableAftee = (isset($userData['currency_code']) && $userData['currency_code'] == 'TWD') ? 1: 0;
3619
3620
3621        if (!$pcFlag) {
3622            // validate
3623            if (
3624                (isset($this->localizeIPLang) && !empty($this->localizeIPLang) && $this->localizeIPLang != 'TWD') // allow taiwan IP only
3625                || ($deviceType == "1" && version_compare($appVersion, $afteeAppSupportedVersion[$deviceType], '<')) // check ios app supported version
3626                || (in_array($deviceType, array(2,3)) && version_compare($appVersion, $afteeAppSupportedVersion[$deviceType], '<')) // check android|amazon app supported version
3627            ) {
3628                $enableAftee = 0;
3629                $isAfteeUser = 0;
3630            }
3631        }else{
3632            
3633            // - validate if PC
3634            if (
3635                $appVersion == 0 && 
3636                $deviceType == 0 && 
3637                $this->localizeDir != "zh-tw" 
3638                || 
3639                ($userData['currency_code'] == 'TWD' && $this->localizeDir != "zh-tw" )
3640                ||
3641                ($userData['currency_code'] != 'TWD' && $this->localizeDir != "zh-tw" )
3642                ||
3643                ($userData['currency_code'] != 'TWD' && $this->localizeDir == "zh-tw" )
3644            ) { 
3645                $enableAftee = 0;
3646                $isAfteeUser = 0;
3647            }
3648        }
3649
3650
3651        // set final values
3652        $this->set('isAfteeUser', false);
3653        $this->set('enableAftee', false);
3654    }
3655
3656    public function queryGuideControl()
3657    {
3658        $this->GuideNavigationbarCategory->openDBReplica();
3659        $datas = $this->GuideNavigationbarCategory->find('all', array(
3660            'fields' => array(
3661                'GuideNavigationbarCategory.id',
3662                'GuideNavigationbarCategory.category_name',
3663                'GuideNavigationbarCategory.lang',
3664                'GuideNavigationbarCategory.display_order',
3665                'GuideNavigationbarContent.id',
3666                'GuideNavigationbarContent.content_name',
3667                'GuideNavigationbarContent.url',
3668                'GuideNavigationbarContent.display_order',
3669                'GuideNavigationbarContent.crawl_flg',
3670                '(SELECT GROUP_CONCAT(DISTINCT (unloggedin_flg)) FROM guide_navigationbar_auth_control WHERE guide_navigationbar_content_id = GuideNavigationbarContent.id) as unloggedin_flg',
3671                '(SELECT GROUP_CONCAT(DISTINCT (membership_type)) FROM guide_navigationbar_membership_control WHERE guide_navigationbar_content_id = GuideNavigationbarContent.id) as membership_type',
3672                '(SELECT GROUP_CONCAT(DISTINCT (currency_code)) FROM guide_navigationbar_currency_control WHERE guide_navigationbar_content_id = GuideNavigationbarContent.id) as currency_code',
3673                '(SELECT GROUP_CONCAT(DISTINCT (browser_language)) FROM guide_navigationbar_browser_lang_control WHERE guide_navigationbar_content_id = GuideNavigationbarContent.id) as browser_language'
3674            ),
3675            'joins' => array(
3676                array(
3677                    'type' => 'LEFT',
3678                    'table' => 'guide_navigationbar_content',
3679                    'alias' => 'GuideNavigationbarContent',
3680                    'conditions' => 'GuideNavigationbarCategory.id = GuideNavigationbarContent.category_id'
3681                )
3682            ),
3683            'conditions' => array(
3684                'GuideNavigationbarCategory.device_type' => 1,
3685                'GuideNavigationbarContent.device_type' => 1
3686            ),
3687            'group' => 'GuideNavigationbarContent.id',
3688            'order' => array(
3689                'GuideNavigationbarCategory.display_order ASC',
3690                'GuideNavigationbarContent.display_order ASC'
3691            ),
3692            'recursive' => -1
3693        ));
3694        $this->GuideNavigationbarCategory->closeDBReplica();
3695
3696        $guideControlCat = array();
3697        if ($datas) {
3698            foreach ($datas as $key=>$data) {
3699                $category_id = $data['GuideNavigationbarCategory']['id'];
3700                $category_name = $data['GuideNavigationbarCategory']['category_name'];
3701
3702                $guideControlCat[$category_id]['category_name'] = $category_name;
3703                $guideControlCat[$category_id]['guide_navigation_bar_content'][$key]['content'] = $data['GuideNavigationbarContent'];
3704                $guideControlCat[$category_id]['guide_navigation_bar_content'][$key]['control'] = $data['0'];
3705            }
3706
3707            $redis = new myRedis();
3708            $redisKey = "dynamic_global_guide_control";
3709
3710            $guideControlCached = $redis->get($redisKey);
3711
3712            if (!$guideControlCached){
3713                $redis->set(array(
3714                    'key' => $redisKey,
3715                    'value' => json_encode($guideControlCat)
3716                ));
3717            }
3718        }
3719
3720        $this->set('GuideNavigationbarCategory', $guideControlCat);
3721    }
3722
3723    // 
3724    public function queryLineHoverControl(){
3725
3726        $returnData = array();
3727
3728        $this->RyugakuSchoolLineSetting->openDBReplica();
3729        $datas = $this->RyugakuSchoolLineSetting->find('all',array(
3730            'fields' => array(
3731                'RyugakuSchoolLineSetting.id',
3732                'RyugakuSchoolLineSetting.line_title',
3733                'RyugakuSchoolLineSetting.line_description',
3734                'RyugakuSchoolLineSetting.line_hover_location_url'
3735            ),
3736            'conditions' => array(),
3737            'recursive' => -1
3738        ));
3739        $this->RyugakuSchoolLineSetting->closeDBReplica();
3740
3741        if ($datas) {
3742            foreach ($datas as $key => $hover) {
3743
3744                $hover=$hover['RyugakuSchoolLineSetting'];
3745
3746                $returnData[] = array(
3747                    'title' => $hover['line_title'],
3748                    'description' => $hover['line_description'],
3749                    'url' => $hover['line_hover_location_url']
3750                );
3751            }
3752        }
3753
3754        $this->set('lineHoverGuide', $returnData);
3755    }
3756
3757    /**
3758     * NJ-27594
3759     * @param String $version - app version,
3760     * @param Int $device_type - 1 - iOS, 2 Android
3761     *
3762     * @return void
3763     */
3764    private function NCPlusPositionUrlScheme($version, $device_type) {
3765        $supportedVersion = Configure::read('nc_plus_positions_url_scheme')[$device_type];
3766        if( version_compare($version, $supportedVersion, '>=')) {
3767            $this->set('position_url_scheme_support', 1);    
3768        } 
3769    }
3770
3771    // NJ-18780 : light plan 
3772    public function checkLitePlanSupported($userData = array(),$pcFlag = false,$page = null){
3773        $enableLitePlan = 0;
3774        $isLitePlanUser = 0;
3775            
3776        $litePlanAppSupportedVersion = Configure::read('lite_plan_app_version_support');
3777        $appVersion = isset($this->request->query['appVersion']) && !empty($this->request->query['appVersion']) ? $this->request->query['appVersion'] : 0;
3778        $deviceType = isset($this->request->query['deviceType']) && !empty($this->request->query['deviceType']) ? $this->request->query['deviceType'] : 0;
3779    
3780        if ($userData) {
3781                // added localize dir overriding to properly get the lite plan data even if the user account is in different language site but currency code is JPY.
3782                $localizeDir = (isset($userData['override_localize_dir'])) ? $userData['override_localize_dir'] : $this->localizeDir;
3783                $setEnableLitePlan = UserTable::checkLitePlanSupported($userData,$pcFlag,$appVersion,$deviceType,$localizeDir,$this->localizeIPLang);
3784    
3785                $enableLitePlan = $setEnableLitePlan['enableLitePlan'];
3786                $isLitePlanUser = $setEnableLitePlan['isLitePlanUser'];
3787    
3788                // - prem complimentary that wan't to change to plan using credit_charge
3789                if (
3790                    isset($userData['payment_plan_id']) && 
3791                    $userData['payment_plan_id'] &&
3792                    $userData['payment_plan_id'] == Configure::read('payment_plans.complimentary_plan') &&
3793                    isset($userData['complimentary_code']) &&
3794                    $userData['complimentary_code'] &&
3795                    in_array($page, array('credit_charge'))
3796                ) {
3797                    # allow check enable lite plan
3798                    if ($this->localizeDir == 'ja') {
3799                        $enableLitePlan = (isset($userData['currency_code']) && $userData['currency_code'] == 'JPY') ? 1: 0;
3800                    } else {
3801                        $enableLitePlan = 0;
3802                    }
3803                }
3804    
3805                if (!empty($page) && !in_array($page, array('credit_charge'))) { 
3806                    $enableLitePlan = 0;
3807                    $isLitePlanUser = 0;
3808
3809                    if ($this->localizeDir == 'ja') {
3810                        $enableLitePlan = 1;
3811                    }
3812                }
3813                
3814                // - allow for corporate charge page 
3815                if (
3816                    isset($userData['corporate_id']) && 
3817                    $userData['corporate_id'] && 
3818                    isset($userData['payment_plan_id']) && 
3819                    $userData['payment_plan_id'] && 
3820                    in_array($page, array('credit_charge'))                    
3821                ) {
3822                    # allow check enable lite plan
3823                    if ($this->localizeDir == 'ja') {
3824                        $enableLitePlan = (isset($userData['currency_code']) && $userData['currency_code'] == 'JPY') ? 1: 0;
3825                    } else {
3826                        $enableLitePlan = 0;
3827                    }
3828                }
3829        }
3830    
3831        // set final values
3832        $this->set('enableLitePlan',$enableLitePlan);
3833        $this->set('isLitePlanUser',$isLitePlanUser);
3834    
3835        // - set return to view 
3836        return array('enableLitePlan' => $enableLitePlan,'isLitePlanUser' => $isLitePlanUser);
3837    
3838    }
3839
3840    /**
3841     * NJ-27262: Resets Users Preset when 
3842     * changed to Chocotto Camp
3843     */
3844    public function resetPresetTextbook($params = []) {
3845        $this->autoRender = false;
3846        $this->layout = false;
3847
3848        if(!$params) {
3849            return;
3850        }
3851
3852        $connect_id = isset($params['connect_id']) ? $params['connect_id'] : Configure::read('textbook_default.chocotto_textbook_connect_id');
3853        
3854        myTools::initializeApiTunnel(array('TextbookUpdatePresetController'));
3855        
3856        $preset = new TextbookUpdatePresetController();
3857
3858        $user = $this->User->find('first', array(
3859            'fields' => array(
3860                'User.id',
3861                'User.api_token',
3862            ),
3863            'conditions' => array(
3864                'User.id' => $params['user_id']
3865            )
3866        ));
3867        
3868        if($user) {
3869            $apiParams = array(
3870                'connect_id' => $connect_id,
3871                'users_api_token' => $user['User']['api_token'],
3872                'nc_terminal_type' => Configure::read('nc_terminal_type.pc')
3873            );
3874    
3875            $preset->params = $apiParams;
3876            $preset->index();
3877        }
3878        
3879    }
3880    
3881    public function setPaypalUser($user = array()) {
3882        
3883        // Check if paypal user
3884        $isPaypalUser = (isset($user['paypal_payer_id']) && isset($user['paypal_payer_email']) && $user['paypal_payer_email']) ? true : false;
3885        $paypal_icon = "/images/pay/Icon_paypal.png";
3886        $paypal_payer_email = (isset($user['paypal_payer_email']) && $user['paypal_payer_email']) ? $user['paypal_payer_email'] : null;
3887
3888        $this->set('isPaypalUser', $isPaypalUser);
3889        $this->set('paypal_icon', $paypal_icon);
3890        $this->set('paypal_payer_email', $paypal_payer_email);
3891    }
3892
3893
3894    /**
3895     * Stripe Payment method
3896     * Check if stripe apple/google pay should be enabled/disabled in app
3897     */
3898    public function checkStripeSupported($userData,$pcFlag = false) {
3899        $stripeAppSupportedVersion = Configure::read('stripe_app_version_support');
3900        $stripeAppSupportedCurrencies = Configure::read('stripe.allowed_currencies');
3901        $appVersion = isset($this->request->query['appVersion']) && !empty($this->request->query['appVersion']) ? $this->request->query['appVersion'] : 0;
3902        $deviceType = isset($this->request->query['deviceType']) && !empty($this->request->query['deviceType']) ? $this->request->query['deviceType'] : 0;
3903        $device = myTools::getDevice();
3904        $userCurrecy = isset($userData['currency_code']) ? $userData['currency_code'] : '';
3905        if(isset($this->mobAppUserData) && $this->mobAppUserData['User']['currency_code']) {
3906            $userCurrecy = $this->mobAppUserData['User']['currency_code'];
3907        } else {
3908            $userCurrecy = isset($this->sharedUserData) && is_array($this->sharedUserData) && $this->sharedUserData['User']['currency_code'] ? $this->sharedUserData['User']['currency_code'] : Configure::read('default.user_currency');
3909        }
3910
3911        // initial values
3912        $isStripeUser = isset($this->isStripeUser) ? $this->isStripeUser : false;
3913        $enableStripe = false;
3914        $stripePaymentType = $device == 3 ? 'apple' : 'google';
3915        $stripeChangePaymentMethod = false;
3916
3917        if (
3918            $isStripeUser ||
3919            (
3920                ($device == "3" && version_compare($appVersion, $stripeAppSupportedVersion[1], '>=') && in_array($userCurrecy, $stripeAppSupportedCurrencies['apple'])) // ios app supported version
3921                || (in_array($device, array(2,4)) && version_compare($appVersion, $stripeAppSupportedVersion[2], '>=') && in_array($userCurrecy, $stripeAppSupportedCurrencies['google'])) // android|amazon app supported version
3922            )
3923        ) {
3924            $enableStripe = true;
3925        }
3926
3927        // Phase 1: Disbale Stripe in some payment pages
3928        if (isset($this->request->params['action']) && !in_array($this->request->params['action'], array('credit', 'creditform', 'native_plan', 'wp_credit', 'wp_creditform', 'mobapp_credit_change_form', 'mobapp_wp_credit_change_form', 'mobapp_wp_credit_retry', 'mobapp_wp_credit_retry_form', 'mobapp_wp_credit_retry_confirm', 'mobapp_credit_retry', 'mobapp_credit_retry_form', 'mobapp_credit_retry_complete'))) {
3929            $enableStripe = false;
3930        }
3931
3932        // Change Payment method: enable for Stripe users only
3933        if (
3934            isset($this->request->params['action']) && in_array($this->request->params['action'], array('mobapp_credit_change_form', 'mobapp_wp_credit_change_form'))
3935        ) {
3936            $stripeChangePaymentMethod = true;
3937            if (!$isStripeUser) {
3938                $enableStripe = false;
3939            }
3940            
3941        }
3942
3943        // Failed Payment Retry: enable for Stripe users only
3944        if (
3945            (isset($this->request->params['action']) && in_array($this->request->params['action'], array('mobapp_wp_credit_retry', 'mobapp_wp_credit_retry_form', 'mobapp_wp_credit_retry_confirm', 'mobapp_credit_retry', 'mobapp_credit_retry_form', 'mobapp_credit_retry_complete')))
3946            && !$isStripeUser
3947        ) {
3948            $enableStripe = false;        
3949        }
3950
3951        // Disable Stripe if KRW and GPay
3952        if ($isStripeUser && $userCurrecy == 'KRW' && $stripePaymentType != 'apple') {
3953            $enableStripe = false;
3954        }
3955
3956        // set final values
3957        $this->set('isStripeUser', $isStripeUser);
3958        $this->set('enableStripe', $enableStripe);
3959        $this->set('stripePaymentType', $stripePaymentType);
3960        $this->set('stripeChangePaymentMethod', $stripeChangePaymentMethod);
3961    }
3962    /**
3963     * ~NJ-29078 - process child receivable payment 
3964     * @param array $familyArr, array $parentArr
3965     */
3966    public function processChildReceivablePayment($familyArr = [], $parentArr = [])
3967    {
3968        $logFileName = 'family_plan';
3969        $curlPayment = "";
3970
3971        if (!$pt = $this->Payment->setUpWithdrawTransaction($familyArr, $logFileName)) {
3972            return false;
3973        }
3974
3975        // ~if zero receivable just return success
3976        if (isset($pt['totalAmount']) && $pt['totalAmount'] == 0) {
3977            $this->log(__METHOD__ . ' No receivable to process' . json_encode($pt), $logFileName);
3978            $curlPayment = "success_order";
3979            return $curlPayment;
3980        }
3981
3982        $familyObj = new UserTable($familyArr);
3983        $parentObj = new UserTable($parentArr);
3984
3985        if ($parentObj->card_company == Configure::read('card_company.zeus')) {
3986            $data = array(
3987                'clientIp' => PaymentTable::getClientIpByCompanyId($parentObj->card_company),
3988                'email' => $parentObj->email,
3989                'sendId' => $parentObj->id,
3990                'money' => $pt['totalAmount'],
3991                'paymentHash' => $pt['payment_hash']
3992            );
3993            // ~process
3994            $curlPayment = $this->ZCharge->charge_with_regsterd_card(json_encode($data));
3995            $curlPayment = PaymentTable::checkPaymentResult($curlPayment);
3996        } else if ($parentObj->card_company == Configure::read('card_company.worldpay')) {
3997            $paymentMethodType = myTools::getWPPaymentMethodType($parentObj->card_brand, 'payment');
3998            $merchantCode = myTools::getWPMerchantCode($paymentMethodType);
3999            $paymentHash = $pt['payment_hash'];
4000            $paymentMethod = explode('_', $paymentMethodType);
4001            $paymentMethod = isset($paymentMethod[0]) ? $paymentMethod[0] : null;
4002            $currencyExponents = Configure::read('worldpay.currency_exponents');
4003            $exponent = $currencyExponents[$parentObj->currency_code];
4004            // get amount with checking currency exponent
4005            $amountArr = myTools::wpGetAmount($exponent, $pt['totalAmount']);
4006            $wpAmount = $amountArr['wpAmount'];
4007
4008            $decodePaymentParams = json_decode($pt['payment_params']);
4009            $paymentFormType = $decodePaymentParams->formType;
4010
4011            $wpParams = array(
4012                'merchantCode' => $merchantCode,
4013                'orderCode' => $paymentHash,
4014                'description' => 'Child Withdrawal Receivables',
4015                'currencyCode' => $parentObj->currency_code,
4016                'exponent' => $exponent,
4017                'amount' => $wpAmount,
4018                'cardToken' => $parentObj->card_token,
4019                'email' => $parentObj->email,
4020                'authenticatedShopperId' => $parentObj->id,
4021                'xmlName' => 'direct_payment_with_token',
4022                'shopperIpAddress' => $_SERVER["REMOTE_ADDR"],
4023                'wpTransactionIdentifier' => $parentObj->wp_transaction_identifier,
4024                'paymentMethod' => $paymentMethod
4025            );
4026
4027            $updateData = array(
4028                'id' => $pt['id'],
4029                'fields' => array('payment_params' => $wpParams)
4030            );
4031
4032            if (!$this->PaymentTransaction->updateWPPaymentTransaction($updateData)) {
4033                $this->log(__METHOD__ . ' Failed to update payment transaction' . json_encode($updateData), $logFileName);
4034            } else {
4035                if (!$pt = $this->PaymentTransaction->getWPPaymentTransaction($paymentHash)) {
4036                    return false;
4037                }
4038            }
4039
4040            // ~process
4041            $res = wpPaymentService::directPayment($wpParams);
4042
4043            $updateData = array(
4044                'id' => $pt['id'],
4045                'fields' => array('response_text' => array('directPayment_response' => $res))
4046            );
4047
4048            if (!$this->PaymentTransaction->updateWPPaymentTransaction($updateData)) {
4049                $this->log(__METHOD__ . ' Failed to update payment transaction' . json_encode($updateData), $logFileName);
4050            }
4051
4052            if (!myTools::checkIfWPPaymentResponseIsAuthorised($res)) {
4053                $curlPayment = "";
4054                $this->log(__METHOD__ . ' Not authorised payment worldpay' . (isset($familyObj->id) ? $familyObj->id : ''), $logFileName);
4055            } else {
4056                $curlPayment = "success_order";
4057            }
4058        } else if ($parentObj->card_company == Configure::read('card_company.aftee')) {
4059            $paymentMethodType = myTools::getWPPaymentMethodType($parentObj->card_brand, 'payment');
4060            $merchantCode = myTools::getWPMerchantCode($paymentMethodType);
4061            $paymentHash = $pt['payment_hash'];
4062            $paymentMethod = explode('_', $paymentMethodType);
4063            $paymentMethod = isset($paymentMethod[0]) ? $paymentMethod[0] : null;
4064            $decodePaymentParams = json_decode($pt['payment_params']);
4065            $paymentFormType = $decodePaymentParams->formType;
4066
4067            $afteeParams = array(
4068                'merchantCode' => $merchantCode,
4069                'orderCode' => $paymentHash,
4070                'description' => 'Family Plan Registration',
4071                'currencyCode' => $parentObj->currency_code,
4072                'amount' => $pt['totalAmount'],
4073                'cardToken' => $parentObj->card_token,
4074                'email' => $parentObj->email,
4075                'authenticatedShopperId' => $parentObj->id,
4076                'shopperIpAddress' => $_SERVER["REMOTE_ADDR"],
4077                'afteeTransactionIdentifier' => $parentObj->aftee_transaction_identifier,
4078                'paymentMethod' => $paymentMethod
4079            );
4080
4081            $updateData = array(
4082                'id' => $pt['id'],
4083                'fields' => array('payment_params' => $afteeParams)
4084            );
4085
4086            if (!$this->PaymentTransaction->updateAfteePaymentTransaction($updateData)) {
4087                $this->log(__METHOD__ . ' Failed to update payment transaction' . json_encode($updateData), $logFileName);
4088            } else {
4089                if (!$pt = $this->PaymentTransaction->getAfteePaymentTransaction($paymentHash)) {
4090                    return false;
4091                }
4092            }
4093
4094            // ~process
4095            $afteeParams = array(
4096                'parent' =>  $parentObj,
4097                'child' =>  $familyObj,
4098                'paymentTransaction' => $pt,
4099                'appreciationFlg' => $familyObj->allow_appreciation_flg,
4100                'tipAmount' => myTools::stringToFloat($familyObj->tip_max_amount)
4101            );
4102
4103            $curlPayment = $this->processChildAfteePayment($afteeParams);
4104        } elseif ($parentObj->card_company == Configure::read('card_company.paypal')) {
4105            $paypalParams = array(
4106                'parent' => $parentObj,
4107                'child' => $familyObj,
4108                'paymentTransaction' => $pt,
4109                'memberStatus' => 'exist'
4110            );
4111
4112            $curlPayment = $this->processChildPaypalPayment($paypalParams);
4113        } else if ($parentObj->card_company == Configure::read('card_company.stripe.apple') || $parentObj->card_company == Configure::read('card_company.stripe.google')){
4114            if (!class_exists('Stripe')) {
4115                App::import('Lib', 'Stripe');
4116            }
4117
4118            $data = array(
4119                'customerId' => $parentObj->stripe_customer_id,
4120                'amount' => $pt['totalAmount'],
4121                'currency' => $parentObj->currency_code,
4122                'paymentMethodID' => $parentObj->stripe_payment_identifier,
4123                'description' => 'Family Plan Receivable Payment',
4124                'sendpoint' => $pt['payment_hash'],
4125                'sendid' => $parentObj->id,
4126                'card_company' => $parentObj->card_company
4127            );
4128            
4129            $stripe = new Stripe();
4130            $curlPayment = $stripe->directPayment($data);    
4131            $curlPayment = myTools::checkStripePaymentResponse($curlPayment);
4132
4133        }
4134
4135        return $curlPayment;
4136    }
4137
4138    // ~NJ-29078 - Withdraw Paypal Process Payment
4139    private function processChildPaypalPayment($params = array())
4140    {
4141        $logFileName = 'family_plan';
4142        if (
4143            !isset($params['child']) ||
4144            !isset($params['parent']) ||
4145            !isset($params['paymentTransaction'])
4146        ) {
4147            $this->log('__METHOD__' . ' missing parameter(s). --> ' . json_encode($params), $logFileName);
4148            return false;
4149        }
4150
4151        // ~check for family parent 
4152        $child = $params['child'];
4153        $parent = $params['parent'];
4154        $pt = $params['paymentTransaction'];
4155        $memberStatus = $params['memberStatus'];
4156
4157        $paymentHash = $pt['payment_hash'];
4158        $ptPassword = $pt['password'];
4159        $ptParams = json_decode($pt['payment_params'], true);
4160
4161        $formType = $ptParams['formType'];
4162        $currencyCode = $ptParams['currencyCode'];
4163        $paymentPlanId = $ptParams['paymentPlanId'];
4164        $priceId = $ptParams['priceId'];
4165        $paymentType = Configure::read('payment_types.payment_receivable');
4166        $platform = $ptParams['platform'];
4167
4168        $membershipStatusIndex = UserTable::getStudentMembershipStatus($child->id);
4169        $currencyId = Configure::read('default.settlement_currency_id'); // set currency id to jpy
4170        $cardCompany = Configure::read('card_company.paypal');
4171        $dateTimeNow = date('Y-m-d H:i:s');
4172
4173        $reservationReceivableAmount = isset($ptParams['reservationReceivableAmount']) ? $ptParams['reservationReceivableAmount'] : 0;
4174        $appreciationReceivableAmount = isset($ptParams['appreciationReceivableAmount']) ? $ptParams['appreciationReceivableAmount'] : 0;
4175        $liveReceivableAmount = isset($ptParams['liveReceivableAmount']) ? $ptParams['liveReceivableAmount'] : 0;
4176
4177
4178        if (!class_exists('PayPal')) {
4179            App::import('Lib', 'PayPal');
4180        }
4181
4182        $PayPal = new PayPal();
4183        $accessTokenData = $PayPal->getAccessToken();
4184
4185        $totalAmount = (int) ($reservationReceivableAmount + $appreciationReceivableAmount + $liveReceivableAmount);
4186
4187        $paypalParams = array(
4188            'ptId' => $pt['id'],
4189            'paypalData' => array('accessTokenData' => $accessTokenData),
4190            'userId' => isset($child->id) ? $child->id : (method_exists($child, 'getId') ? $child->getId() : null),
4191            'money' => $totalAmount,
4192            'formType' => $formType,
4193            'priceId' => $priceId,
4194            'paymentId' => $paymentPlanId,
4195            'paymentType' => $paymentType
4196        );
4197
4198        $receivables = [
4199            'payment_credit_receivable' => $reservationReceivableAmount,
4200            'payment_credit_appreciation_receivable' => $appreciationReceivableAmount,
4201            'payment_live_lesson_receivable' => $liveReceivableAmount
4202        ];
4203
4204        // break if error
4205        if (!isset($accessTokenData['access_token'])) {
4206            $this->log(__METHOD__ . ' paypal error --> ' . json_encode($accessTokenData) . ' --> ' . json_encode($params), $logFileName);
4207            $this->savePaypalFailedSettlement($receivables, $paypalParams);
4208            return;
4209        }
4210
4211        $createOrderParams = array(
4212            'accessToken' => $accessTokenData['access_token'],
4213            'paypalRequestId' => $pt['id'],
4214            'intent' => 'CAPTURE',
4215            'paymentHash' => $paymentHash,
4216            'userId' => $parent->id ?? null,
4217            'currencyCode' => $currencyCode,
4218            'amount' => $totalAmount,
4219            'billingAgreementId' => $parent->paypal_billing_agreement_id ?? null
4220        );
4221
4222        // add mock application code
4223        if (isset($request['mockResponse'])) {
4224            $createOrderParams['mockResponse'] = $request['mockResponse'];
4225        }
4226
4227        $curlPayment = $PayPal->createOrder($createOrderParams);
4228        $paypalParams['paypalData']['createOrder'] = $curlPayment;
4229        $paymentSuccess = isset($curlPayment['status']) && $curlPayment['status'] == 'COMPLETED' ? true : false;
4230
4231        if (!$paymentSuccess) {
4232            $this->log(__METHOD__ . ' paypal error --> ' . json_encode($curlPayment) . ' --> ' . json_encode($params), $logFileName);
4233            $this->savePaypalFailedSettlement($receivables, $paypalParams);
4234            return;
4235        }
4236
4237        // create payment
4238        $savePaymentArr = array(
4239            'user_id' => $child->id,
4240            'amount' => $totalAmount,
4241            'status' => 1,
4242            'reference_id' => $child->id,
4243            'payment_transaction_password' => $ptPassword,
4244            'card_company' => $cardCompany,
4245            'param1' => json_encode($paypalParams),
4246            'form_type' => $formType,
4247            'ordd' => $paymentHash,
4248            'transaction_code' => $paymentHash,
4249            'currency_id' => $currencyId,
4250            'currency_code' => $currencyCode,
4251            'payment_id' => $paymentPlanId,
4252            'price_id' => $priceId,
4253            'payment_type' => $paymentType
4254        );
4255
4256        $this->Payment->clear();
4257        $this->Payment->create();
4258        $this->Payment->set($savePaymentArr);
4259        $this->Payment->validate = array();
4260
4261        // update/add user`s settlement amount
4262        $this->User->updateUserPayments($savePaymentArr);
4263
4264        // set payment_id
4265        $paymentSaveID = $this->Payment->id;
4266        $data = array('payment_id' => $paymentSaveID);
4267        $paymentType = Configure::read('payment_types.payment_receivable');
4268
4269        // reservation receivable
4270        if ($reservationReceivableAmount > 0) {
4271            $savePaymentArr = array(
4272                'user_id' => $child->id,
4273                'amount' => $reservationReceivableAmount,
4274                'status' => 1,
4275                'type_id' => 1,
4276                'reference_id' => $child->id,
4277                'card_company' => $cardCompany,
4278                'param1' => json_encode($data),
4279                'form_type' => Configure::read('payment_credit_receivable'),
4280                'ordd' => $paymentHash,
4281                'transaction_code' => $paymentHash,
4282                'currency_id' => $currencyId,
4283                'currency_code' => $currencyCode,
4284                'payment_id' => $paymentPlanId,
4285                'price_id' => $priceId,
4286                'payment_type' => $paymentType
4287            );
4288
4289            // create new payment for reservation receivable
4290            $this->Payment->clear();
4291            $this->Payment->create();
4292            $this->Payment->set($savePaymentArr);
4293            if (!$this->Payment->save()) {
4294                $this->log(__METHOD__ . ' Failed to save payment data for reservation receivable.' . json_encode($savePaymentArr), $logFileName);
4295                return;
4296            }
4297
4298            // set payment_id
4299            $rrPaymentID = $this->Payment->id;
4300
4301            //update/add user`s settlement amount
4302            $this->User->updateUserPayments($savePaymentArr);
4303
4304            // set payment receivable statuses to 2 - received
4305            $this->PaymentReceivable->updateReceivableReservationPayment(
4306                $child->id,
4307                array(
4308                    'status' => 2,
4309                    'payment_id' => $rrPaymentID,
4310                    'payment_collection_date' => $dateTimeNow,
4311                    'card_company' => $cardCompany,
4312                    'payment_plan_id' => $paymentPlanId,
4313                    'membership_type_index' => $membershipStatusIndex
4314                ),
4315                array(
4316                    'PaymentReceivable.user_id' => $child->id,
4317                    'PaymentReceivable.status' => 0,
4318                    'PaymentReceivable.payment_element_type' => Configure::read('payment_element_type.reservation'),
4319                    'PaymentReceivable.created <=' => $dateTimeNow
4320                )
4321            );
4322        }
4323
4324        // appreciation receivable
4325        if ($appreciationReceivableAmount > 0) {
4326            $savePaymentArr = array(
4327                'user_id' => $child->id,
4328                'amount' => $appreciationReceivableAmount,
4329                'status' => 1,
4330                'type_id' => 1,
4331                'reference_id' => $child->id,
4332                'card_company' => $cardCompany,
4333                'param1' => json_encode($data),
4334                'form_type' => Configure::read('payment_credit_appreciation_receivable'),
4335                'ordd' => $paymentHash,
4336                'transaction_code' => $paymentHash,
4337                'currency_id' => $currencyId,
4338                'currency_code' => $currencyCode,
4339                'payment_id' => $paymentPlanId,
4340                'price_id' => $priceId,
4341                'payment_type' => $paymentType
4342            );
4343
4344            // create new payment for appreciation receivable
4345            $this->Payment->clear();
4346            $this->Payment->create();
4347            $this->Payment->set($savePaymentArr);
4348            if (!$this->Payment->save()) {
4349                $this->log(__METHOD__ . ' Failed to save payment data for appreciation receivable.' . json_encode($savePaymentArr), $logFileName);
4350                return;
4351            }
4352
4353            // set payment_id
4354            $arPaymentID = $this->Payment->id;
4355
4356            //update/add user`s settlement amount
4357            $this->User->updateUserPayments($savePaymentArr);
4358
4359            // set payment receivable statuses to 2 - received
4360            $this->PaymentReceivable->updateReceivableReservationPayment(
4361                $child->id,
4362                array(
4363                    'status' => 2,
4364                    'payment_id' => $arPaymentID,
4365                    'payment_collection_date' => $dateTimeNow,
4366                    'card_company' => $cardCompany,
4367                    'payment_plan_id' => $paymentPlanId,
4368                    'membership_type_index' => $membershipStatusIndex
4369                ),
4370                array(
4371                    'PaymentReceivable.user_id' => $child->id,
4372                    'PaymentReceivable.status' => 0,
4373                    'PaymentReceivable.payment_element_type' => Configure::read('payment_element_type.appreciation'),
4374                    'PaymentReceivable.created <=' => $dateTimeNow
4375                )
4376            );
4377        }
4378
4379        // live receivable
4380        if ($liveReceivableAmount > 0) {
4381            $savePaymentArr = array(
4382                'user_id' => $child->id,
4383                'amount' => $liveReceivableAmount,
4384                'status' => 1,
4385                'type_id' => 1,
4386                'reference_id' => $child->id,
4387                'card_company' => $cardCompany,
4388                'param1' => json_encode($data),
4389                'form_type' => Configure::read('payment_live_lesson_receivable'),
4390                'ordd' => $paymentHash,
4391                'transaction_code' => $paymentHash,
4392                'currency_id' => $currencyId,
4393                'currency_code' => $currencyCode,
4394                'payment_id' => $paymentPlanId,
4395                'price_id' => $priceId,
4396                'payment_type' => $paymentType
4397            );
4398
4399            // create new payment for live receivable
4400            $this->Payment->clear();
4401            $this->Payment->create();
4402            $this->Payment->set($savePaymentArr);
4403            if (!$this->Payment->save()) {
4404                $this->log(__METHOD__ . ' Failed to save payment data for live receivable.' . json_encode($savePaymentArr), $logFileName);
4405                return;
4406            }
4407
4408            // set payment_id
4409            $lrPaymentID = $this->Payment->id;
4410
4411            //update/add user`s settlement amount
4412            $this->User->updateUserPayments($savePaymentArr);
4413
4414            // set payment receivable statuses to 2 - received
4415            $this->PaymentReceivable->updateReceivableReservationPayment(
4416                $child->id,
4417                array(
4418                    'status' => 2,
4419                    'payment_id' => $lrPaymentID,
4420                    'payment_collection_date' => $dateTimeNow,
4421                    'card_company' => $cardCompany,
4422                    'payment_plan_id' => $paymentPlanId,
4423                    'membership_type_index' => $membershipStatusIndex
4424                ),
4425                array(
4426                    'PaymentReceivable.user_id' => $child->id,
4427                    'PaymentReceivable.status' => 0,
4428                    'PaymentReceivable.payment_element_type' => Configure::read('payment_element_type.live'),
4429                    'PaymentReceivable.created <=' => $dateTimeNow
4430                )
4431            );
4432        }
4433
4434        $fields = array('status' => 1);
4435        if (isset($paypalParams)) {
4436            $fields['response_text'] = array('paypal_response' => $paypalParams);
4437        }
4438
4439        // update payment transaction
4440        $this->PaymentTransaction->updateWPPaymentTransaction(array('id' => $ptId ?? null, 'fields' => $fields));
4441
4442        return 'success_order';
4443    }
4444
4445    // ~NJ-29078 - Withdraw Aftee Process Payment
4446    private function processChildAfteePayment($params = array())
4447    {
4448        $logFileName = 'family_plan';
4449        if (
4450            !isset($params['child']) ||
4451            !isset($params['parent']) ||
4452            !isset($params['paymentTransaction'])
4453        ) {
4454            $this->log('__METHOD__' . ' missing parameter(s). --> ' . json_encode($params), $logFileName);
4455            return false;
4456        }
4457
4458        $parent = $params['parent'];
4459        $child = $params['child'];
4460        $pt = $params['paymentTransaction'];
4461
4462        $ptId = $pt['id'];
4463        $ptPassword = $pt['password'] ?? '';
4464        $ptParams = json_decode($pt['payment_params'], true);
4465
4466        $formType = $ptParams['formType'];
4467        $currencyCode = $ptParams['currencyCode'] ?? null;
4468        $paymentPlanId = $ptParams['paymentPlanId'] ?? null;
4469        $priceId = $ptParams['priceId'] ?? null;
4470        $paymentType = $ptParams['paymentType'] ?? null;
4471        $platform = $ptParams['platform'] ?? null;
4472        $paymentHash = $ptParams['orderCode'] ?? null;
4473        $afteeTransactionIdentifier = $ptParams['afteeTransactionIdentifier'] ?? null;
4474
4475        $membershipStatusIndex = UserTable::getStudentMembershipStatus(isset($child->id) ? $child->id : (method_exists($child, 'getId') ? $child->getId() : null));
4476        $currencyId = Configure::read('default.settlement_currency_id'); // set currency id to jpy
4477        $cardCompany = Configure::read('card_company.aftee');
4478        $dateTimeNow = date('Y-m-d H:i:s');
4479
4480        $appreciationFlg = 0;
4481        // $this->log(__METHOD__ . ' aftee debug --> ' . json_encode($params), $logFileName);
4482        // $this->log(__METHOD__ . ' aftee debug --> ' . json_encode($pt), $logFileName);
4483        // $this->log(__METHOD__ . ' aftee debug --> ' . $paymentHash, $logFileName);
4484
4485        // initial aftee amount
4486        $totalAmount = (int)($ptParams['paymentAmount'] ?? 0);
4487        if ($totalAmount > 0) {
4488            if (isset($parent->aftee_transaction_identifier) && !empty($parent->aftee_transaction_identifier)) {
4489                $related_id = $parent->aftee_transaction_identifier;
4490            } else {
4491                $related_id = $afteeTransactionIdentifier;
4492            }
4493
4494            // load PayPal class
4495            if (!class_exists('AfteePaymentService')) {
4496                App::import('Lib', 'AfteePaymentService');
4497            }
4498
4499            $afteeChecksumData = array(
4500                'shopItemId' => "AFTEE" . $formType,
4501                'itemName' => 'FamilyPlanRegistration',
4502                'itemPrice' => $totalAmount,
4503                'itemCount' => 1,
4504                'customerPhoneNumber' => $parent->phone_number,
4505                'customerEmail' => $parent->email,
4506                'shopTransactionNo' => $paymentHash,
4507                'userID' => $parent->id
4508            );
4509            $afteeService = new AfteePaymentService();
4510            $checksum = $afteeService->generateChecksum($afteeChecksumData, false);
4511
4512
4513            $afteeData = array(
4514                'authentication_token' => $parent->card_token,
4515                'related_id' => $related_id,
4516                'checksum' => $checksum['checksum'],
4517                'shop_transaction_no' => $paymentHash,
4518                'transaction_options' => array(1)
4519            );
4520
4521            $afteePaymentData = array_merge($afteeData, $checksum['settlementData']);
4522
4523            // process Aftee direct payment
4524            $res = $afteeService->directPayment($afteePaymentData);
4525            $checkRes = json_decode($res, true);
4526            // $this->log(__METHOD__ . ' aftee --> ' . json_encode($afteePaymentData) . ' --> ' . json_encode($checkRes), $logFileName);
4527
4528            if (isset($checkRes['object']) && $checkRes['object'] == 'transaction') {
4529                $paymentSuccess = true;
4530            } else if (!array_key_exists("object", $checkRes) || (isset($checkRes['object']) && $checkRes['object'] == 'error')) {
4531                $paymentSuccess = false;
4532            }
4533        } else {
4534            // zero payment
4535            $checkRes = array('aftee zero payment --> family plan registration');
4536            $paymentSuccess = true;
4537        }
4538
4539
4540        if (!$paymentSuccess) {
4541            $this->log(__METHOD__ . ' aftee error --> ' . json_encode($checkRes) . ' --> ' . json_encode($params), $logFileName);
4542            return;
4543        }
4544
4545        // payment history data amount
4546        $reservationReceivableAmount = isset($ptParams['reservationReceivableAmount']) ? $ptParams['reservationReceivableAmount'] : 0;
4547        $appreciationReceivableAmount = isset($ptParams['appreciationReceivableAmount']) ? $ptParams['appreciationReceivableAmount'] : 0;
4548        $liveReceivableAmount = isset($ptParams['liveReceivableAmount']) ? $ptParams['liveReceivableAmount'] : 0;
4549
4550        // create payment
4551        $savePaymentArr = array(
4552            'user_id' => $child->id ?? (method_exists($child, 'getId') ? $child->getId() : null),
4553            'status' => 1,
4554            'reference_id' => $child->id ?? (method_exists($child, 'getId') ? $child->getId() : null),
4555            'payment_transaction_password' => $ptPassword,
4556            'card_company' => $cardCompany,
4557            'param1' => json_encode($checkRes),
4558            'form_type' => $formType,
4559            'ordd' => $paymentHash,
4560            'transaction_code' => $paymentHash,
4561            'currency_id' => $currencyId,
4562            'currency_code' => $currencyCode,
4563            'payment_id' => $paymentPlanId,
4564            'price_id' => $priceId,
4565            'payment_type' => $paymentType
4566        );
4567
4568        $this->Payment->clear();
4569        $this->Payment->create();
4570        $this->Payment->set($savePaymentArr);
4571        $this->Payment->validate = array();
4572
4573        // update/add user`s settlement amount
4574        $this->User->updateUserPayments($savePaymentArr);
4575
4576        // set payment_id
4577        $paymentSaveID = $this->Payment->id;
4578        $data = array('payment_id' => $paymentSaveID);
4579        $paymentType = Configure::read('payment_types.payment_receivable');
4580
4581        // reservation receivable
4582        if ($reservationReceivableAmount > 0) {
4583            $savePaymentArr = array(
4584                'user_id' => $child->id,
4585                'amount' => $reservationReceivableAmount,
4586                'status' => 1,
4587                'type_id' => 1,
4588                'reference_id' => $child->id,
4589                'card_company' => $cardCompany,
4590                'param1' => json_encode($data),
4591                'form_type' => Configure::read('payment_credit_receivable'),
4592                'ordd' => $paymentHash,
4593                'transaction_code' => $paymentHash,
4594                'currency_id' => $currencyId,
4595                'currency_code' => $currencyCode,
4596                'payment_id' => $paymentPlanId,
4597                'price_id' => $priceId,
4598                'payment_type' => $paymentType
4599            );
4600
4601            // create new payment for reservation receivable
4602            $this->Payment->clear();
4603            $this->Payment->create();
4604            $this->Payment->set($savePaymentArr);
4605            if (!$this->Payment->save()) {
4606                $this->log(__METHOD__ . ' Failed to save payment data for reservation receivable.' . json_encode($savePaymentArr), $logFileName);
4607                return;
4608            }
4609
4610            // set payment_id
4611            $rrPaymentID = $this->Payment->id;
4612
4613            //update/add user`s settlement amount
4614            $this->User->updateUserPayments($savePaymentArr);
4615
4616            // set payment receivable statuses to 2 - received
4617            $this->PaymentReceivable->updateReceivableReservationPayment(
4618                $child->id,
4619                array(
4620                    'status' => 2,
4621                    'payment_id' => $rrPaymentID,
4622                    'payment_collection_date' => $dateTimeNow,
4623                    'card_company' => $cardCompany,
4624                    'payment_plan_id' => $paymentPlanId,
4625                    'membership_type_index' => $membershipStatusIndex
4626                ),
4627                array(
4628                    'PaymentReceivable.user_id' => $child->id,
4629                    'PaymentReceivable.status' => 0,
4630                    'PaymentReceivable.payment_element_type' => Configure::read('payment_element_type.reservation'),
4631                    'PaymentReceivable.created <=' => $dateTimeNow
4632                )
4633            );
4634        }
4635
4636        // appreciation receivable
4637        if ($appreciationReceivableAmount > 0) {
4638            $savePaymentArr = array(
4639                'user_id' => $child->id,
4640                'amount' => $appreciationReceivableAmount,
4641                'status' => 1,
4642                'type_id' => 1,
4643                'reference_id' => $child->id,
4644                'card_company' => $cardCompany,
4645                'param1' => json_encode($data),
4646                'form_type' => Configure::read('payment_credit_appreciation_receivable'),
4647                'ordd' => $paymentHash,
4648                'transaction_code' => $paymentHash,
4649                'currency_id' => $currencyId,
4650                'currency_code' => $currencyCode,
4651                'payment_id' => $paymentPlanId,
4652                'price_id' => $priceId,
4653                'payment_type' => $paymentType
4654            );
4655
4656            // create new payment for appreciation receivable
4657            $this->Payment->clear();
4658            $this->Payment->create();
4659            $this->Payment->set($savePaymentArr);
4660            if (!$this->Payment->save()) {
4661                $this->log(__METHOD__ . ' Failed to save payment data for appreciation receivable.' . json_encode($savePaymentArr), $logFileName);
4662                return;
4663            }
4664
4665            // set payment_id
4666            $arPaymentID = $this->Payment->id;
4667
4668            //update/add user`s settlement amount
4669            $this->User->updateUserPayments($savePaymentArr);
4670
4671            // set payment receivable statuses to 2 - received
4672            $this->PaymentReceivable->updateReceivableReservationPayment(
4673                $child->id,
4674                array(
4675                    'status' => 2,
4676                    'payment_id' => $arPaymentID,
4677                    'payment_collection_date' => $dateTimeNow,
4678                    'card_company' => $cardCompany,
4679                    'payment_plan_id' => $paymentPlanId,
4680                    'membership_type_index' => $membershipStatusIndex
4681                ),
4682                array(
4683                    'PaymentReceivable.user_id' => $child->id,
4684                    'PaymentReceivable.status' => 0,
4685                    'PaymentReceivable.payment_element_type' => Configure::read('payment_element_type.appreciation'),
4686                    'PaymentReceivable.created <=' => $dateTimeNow
4687                )
4688            );
4689        }
4690
4691        // live receivable
4692        if ($liveReceivableAmount > 0) {
4693            $savePaymentArr = array(
4694                'user_id' => $child->id,
4695                'amount' => $liveReceivableAmount,
4696                'status' => 1,
4697                'type_id' => 1,
4698                'reference_id' => $child->id,
4699                'card_company' => $cardCompany,
4700                'param1' => json_encode($data),
4701                'form_type' => Configure::read('payment_live_lesson_receivable'),
4702                'ordd' => $paymentHash,
4703                'transaction_code' => $paymentHash,
4704                'currency_id' => $currencyId,
4705                'currency_code' => $currencyCode,
4706                'payment_id' => $paymentPlanId,
4707                'price_id' => $priceId,
4708                'payment_type' => $paymentType
4709            );
4710
4711            // create new payment for live receivable
4712            $this->Payment->clear();
4713            $this->Payment->create();
4714            $this->Payment->set($savePaymentArr);
4715            if (!$this->Payment->save()) {
4716                $this->log(__METHOD__ . ' Failed to save payment data for live receivable.' . json_encode($savePaymentArr), $logFileName);
4717                return;
4718            }
4719
4720            // set payment_id
4721            $lrPaymentID = $this->Payment->id;
4722
4723            //update/add user`s settlement amount
4724            $this->User->updateUserPayments($savePaymentArr);
4725
4726            // set payment receivable statuses to 2 - received
4727            $this->PaymentReceivable->updateReceivableReservationPayment(
4728                $child->id,
4729                array(
4730                    'status' => 2,
4731                    'payment_id' => $lrPaymentID,
4732                    'payment_collection_date' => $dateTimeNow,
4733                    'card_company' => $cardCompany,
4734                    'payment_plan_id' => $paymentPlanId,
4735                    'membership_type_index' => $membershipStatusIndex
4736                ),
4737                array(
4738                    'PaymentReceivable.user_id' => $child->id,
4739                    'PaymentReceivable.status' => 0,
4740                    'PaymentReceivable.payment_element_type' => Configure::read('payment_element_type.live'),
4741                    'PaymentReceivable.created <=' => $dateTimeNow
4742                )
4743            );
4744        }
4745
4746        $fields = array('status' => 1);
4747        if (isset($checkRes)) {
4748            $fields['response_text'] = array('aftee' => $checkRes);
4749        }
4750
4751        // update payment transaction
4752        $this->PaymentTransaction->updateWPPaymentTransaction(array('id' => $ptId, 'fields' => $fields));
4753
4754        return 'success_order';
4755    }
4756
4757    /**
4758     * ~NJ-29078 - process child receivable payment 
4759     * @param array $userArr
4760     */
4761    public function processParentReceivablePayment($userArr = [])
4762    {
4763        $logFileName = 'family_plan';
4764        $curlPayment = "";
4765
4766        if (!$pt = $this->Payment->setUpWithdrawTransaction($userArr, $logFileName)) {
4767            return false;
4768        }
4769
4770        if (isset($pt['totalAmount']) && $pt['totalAmount'] == 0) {
4771            $this->log(__METHOD__ . ' No receivable to process' . json_encode($pt), $logFileName);
4772            $curlPayment = "success_order";
4773            return $curlPayment;
4774        }
4775
4776        $userObj = new UserTable($userArr);
4777
4778        if ($userObj->card_company == Configure::read('card_company.zeus')) {
4779            $data = array(
4780                'clientIp' => PaymentTable::getClientIpByCompanyId($userObj->card_company),
4781                'email' => $userObj->email,
4782                'sendId' => $userObj->id,
4783                'money' => $pt['totalAmount'],
4784                'paymentHash' => $pt['payment_hash']
4785            );
4786            // ~process
4787            $curlPayment = $this->ZCharge->charge_with_regsterd_card(json_encode($data));
4788            $curlPayment = PaymentTable::checkPaymentResult($curlPayment);
4789        } else if ($userObj->card_company == Configure::read('card_company.worldpay')) {
4790            $paymentMethodType = myTools::getWPPaymentMethodType($userObj->card_brand, 'payment');
4791            $merchantCode = myTools::getWPMerchantCode($paymentMethodType);
4792            $paymentHash = $pt['payment_hash'];
4793            $paymentMethod = explode('_', $paymentMethodType);
4794            $paymentMethod = isset($paymentMethod[0]) ? $paymentMethod[0] : null;
4795            $currencyExponents = Configure::read('worldpay.currency_exponents');
4796            $exponent = $currencyExponents[$userObj->currency_code];
4797            // get amount with checking currency exponent
4798            $amountArr = myTools::wpGetAmount($exponent, $pt['totalAmount']);
4799            $wpAmount = $amountArr['wpAmount'];
4800
4801            $decodePaymentParams = json_decode($pt['payment_params']);
4802            $paymentFormType = $decodePaymentParams->formType;
4803
4804            $wpParams = array(
4805                'merchantCode' => $merchantCode,
4806                'orderCode' => $paymentHash,
4807                'description' => 'Child Withdrawal Receivables',
4808                'currencyCode' => $userObj->currency_code,
4809                'exponent' => $exponent,
4810                'amount' => $wpAmount,
4811                'cardToken' => $userObj->card_token,
4812                'email' => $userObj->email,
4813                'authenticatedShopperId' => $userObj->id,
4814                'xmlName' => 'direct_payment_with_token',
4815                'shopperIpAddress' => $_SERVER["REMOTE_ADDR"],
4816                'wpTransactionIdentifier' => $userObj->wp_transaction_identifier,
4817                'paymentMethod' => $paymentMethod
4818            );
4819
4820            $updateData = array(
4821                'id' => $pt['id'],
4822                'fields' => array('payment_params' => $wpParams)
4823            );
4824
4825            if (!$this->PaymentTransaction->updateWPPaymentTransaction($updateData)) {
4826                $this->log(__METHOD__ . ' Failed to update payment transaction' . json_encode($updateData), $logFileName);
4827            } else {
4828                if (!$pt = $this->PaymentTransaction->getWPPaymentTransaction($paymentHash)) {
4829                    return false;
4830                }
4831            }
4832
4833            // ~process
4834            $res = wpPaymentService::directPayment($wpParams);
4835
4836            $updateData = array(
4837                'id' => $pt['id'],
4838                'fields' => array('response_text' => array('directPayment_response' => $res))
4839            );
4840
4841            if (!$this->PaymentTransaction->updateWPPaymentTransaction($updateData)) {
4842                $this->log(__METHOD__ . ' Failed to update payment transaction' . json_encode($updateData), $logFileName);
4843            }
4844
4845            if (!myTools::checkIfWPPaymentResponseIsAuthorised($res)) {
4846                $curlPayment = "";
4847                $this->log(__METHOD__ . ' Not authorised payment worldpay' . $userObj->id, $logFileName);
4848            } else {
4849                $curlPayment = "success_order";
4850            }
4851        } else if ($userObj->card_company == Configure::read('card_company.aftee')) {
4852            $paymentMethodType = myTools::getWPPaymentMethodType($userObj->card_brand, 'payment');
4853            $merchantCode = myTools::getWPMerchantCode($paymentMethodType);
4854            $paymentHash = $pt['payment_hash'];
4855            $paymentMethod = explode('_', $paymentMethodType);
4856            $paymentMethod = isset($paymentMethod[0]) ? $paymentMethod[0] : null;
4857            $decodePaymentParams = json_decode($pt['payment_params']);
4858            $paymentFormType = $decodePaymentParams->formType;
4859
4860            $afteeParams = array(
4861                'merchantCode' => $merchantCode,
4862                'orderCode' => $paymentHash,
4863                'description' => 'Family Plan Registration',
4864                'currencyCode' => $userObj->currency_code,
4865                'amount' => $pt['totalAmount'],
4866                'cardToken' => $userObj->card_token,
4867                'email' => $userObj->email,
4868                'authenticatedShopperId' => $userObj->id,
4869                'shopperIpAddress' => $_SERVER["REMOTE_ADDR"],
4870                'afteeTransactionIdentifier' => $userObj->aftee_transaction_identifier,
4871                'paymentMethod' => $paymentMethod
4872            );
4873
4874            $updateData = array(
4875                'id' => $pt['id'],
4876                'fields' => array('payment_params' => $afteeParams)
4877            );
4878
4879            if (!$this->PaymentTransaction->updateAfteePaymentTransaction($updateData)) {
4880                $this->log(__METHOD__ . ' Failed to update payment transaction' . json_encode($updateData), $logFileName);
4881            } else {
4882                if (!$pt = $this->PaymentTransaction->getAfteePaymentTransaction($paymentHash)) {
4883                    return false;
4884                }
4885            }
4886
4887            // ~process
4888            $afteeParams = array(
4889                'user' =>  $userObj,
4890                'paymentTransaction' => $pt,
4891                'appreciationFlg' => $userObj->allow_appreciation_flg,
4892                'tipAmount' => myTools::stringToFloat($userObj->tip_max_amount)
4893            );
4894
4895            $curlPayment = $this->processParentAfteePayment($afteeParams);
4896        } elseif ($userObj->card_company == Configure::read('card_company.paypal')) {
4897            $paypalParams = array(
4898                'user' => $userObj,
4899                'paymentTransaction' => $pt,
4900                'memberStatus' => 'exist'
4901            );
4902
4903            $curlPayment = $this->processParentPaypalPayment($paypalParams);
4904        } else if ($userObj->card_company == Configure::read('card_company.stripe.apple') || $userObj->card_company == Configure::read('card_company.stripe.google')){
4905            if (!class_exists('Stripe')) {
4906                App::import('Lib', 'Stripe');
4907            }
4908
4909            $data = array(
4910                'customerId' => $userObj->stripe_customer_id,
4911                'amount' => $pt['totalAmount'],
4912                'currency' => $userObj->currency_code,
4913                'paymentMethodID' => $userObj->stripe_payment_identifier,
4914                'description' => 'Family Plan Receivable Payment',
4915                'sendpoint' => $pt['payment_hash'],
4916                'sendid' => $userObj->id,
4917                'card_company' => $userObj->card_company
4918            );
4919            
4920            $stripe = new Stripe();
4921            $curlPayment = $stripe->directPayment($data);    
4922            $curlPayment = myTools::checkStripePaymentResponse($curlPayment);
4923
4924        }
4925
4926        return $curlPayment;
4927    }
4928
4929    // ~NJ-29078 - Withdraw Paypal Process Payment
4930    private function processParentPaypalPayment($params = array())
4931    {
4932        $logFileName = 'family_plan';
4933        if (
4934            !isset($params['user']) ||
4935            !isset($params['paymentTransaction'])
4936        ) {
4937            $this->log('__METHOD__' . ' missing parameter(s). --> ' . json_encode($params), $logFileName);
4938            return false;
4939        }
4940
4941        // ~check for family parent 
4942        $user = $params['user'];
4943        $pt = $params['paymentTransaction'];
4944        $memberStatus = $params['memberStatus'];
4945        $paymentHash = $pt['payment_hash'] ?? null;
4946        $ptPassword = $pt['password'] ?? '';
4947        $ptParams = json_decode($pt['payment_params'] ?? '', true);
4948
4949        $formType = $ptParams['formType'] ?? null;
4950        $currencyCode = $ptParams['currencyCode'] ?? null;
4951        $paymentPlanId = $ptParams['paymentPlanId'] ?? null;
4952        $priceId = $ptParams['priceId'] ?? null;
4953        $paymentType = Configure::read('payment_types.payment_receivable');
4954        $platform = $ptParams['platform'] ?? null;
4955
4956        $membershipStatusIndex = UserTable::getStudentMembershipStatus(method_exists($user, 'getId') ? $user->getId() : (isset($user->id) ? $user->id : null));
4957        $currencyId = Configure::read('default.settlement_currency_id'); // set currency id to jpy
4958        $cardCompany = Configure::read('card_company.paypal');
4959        $dateTimeNow = date('Y-m-d H:i:s');
4960
4961        $reservationReceivableAmount = isset($ptParams['reservationReceivableAmount']) ? $ptParams['reservationReceivableAmount'] : 0;
4962        $appreciationReceivableAmount = isset($ptParams['appreciationReceivableAmount']) ? $ptParams['appreciationReceivableAmount'] : 0;
4963        $liveReceivableAmount = isset($ptParams['liveReceivableAmount']) ? $ptParams['liveReceivableAmount'] : 0;
4964
4965
4966        if (!class_exists('PayPal')) {
4967            App::import('Lib', 'PayPal');
4968        }
4969
4970        $PayPal = new PayPal();
4971        $accessTokenData = $PayPal->getAccessToken();
4972
4973        $totalAmount = (int) ($reservationReceivableAmount + $appreciationReceivableAmount + $liveReceivableAmount);
4974
4975        $paypalParams = array(
4976            'ptId' => $pt['id'],
4977            'paypalData' => array('accessTokenData' => $accessTokenData),
4978            'userId' => method_exists($user, 'getId') ? $user->getId() : ($user->id ?? null),
4979            'money' => $totalAmount,
4980            'formType' => $formType,
4981            'priceId' => $priceId,
4982            'paymentId' => $paymentPlanId,
4983            'paymentType' => $paymentType
4984        );
4985
4986        $receivables = [
4987            'payment_credit_receivable' => $reservationReceivableAmount,
4988            'payment_credit_appreciation_receivable' => $appreciationReceivableAmount,
4989            'payment_live_lesson_receivable' => $liveReceivableAmount
4990        ];
4991
4992        // break if error
4993        if (!isset($accessTokenData['access_token'])) {
4994            $this->log(__METHOD__ . ' paypal error --> ' . json_encode($accessTokenData) . ' --> ' . json_encode($params), $logFileName);
4995            $this->savePaypalFailedSettlement($receivables, $paypalParams);
4996            return;
4997        }
4998
4999        $createOrderParams = array(
5000            'accessToken' => $accessTokenData['access_token'],
5001            'paypalRequestId' => $pt['id'],
5002            'intent' => 'CAPTURE',
5003            'paymentHash' => $paymentHash,
5004            'userId' => $user->id ?? null,
5005            'currencyCode' => $currencyCode,
5006            'amount' => $totalAmount,
5007            'billingAgreementId' => $user->paypal_billing_agreement_id ?? null
5008        );
5009
5010        // add mock application code
5011        if (isset($request['mockResponse'])) {
5012            $createOrderParams['mockResponse'] = $request['mockResponse'];
5013        }
5014
5015        $curlPayment = $PayPal->createOrder($createOrderParams);
5016        $paypalParams['paypalData']['createOrder'] = $curlPayment;
5017        $paymentSuccess = isset($curlPayment['status']) && $curlPayment['status'] == 'COMPLETED' ? true : false;
5018
5019        if (!$paymentSuccess) {
5020            //$this->log(__METHOD__ . ' paypal error --> ' . json_encode($curlPayment) . ' --> ' . json_encode($params), $logFileName);
5021            $this->savePaypalFailedSettlement($receivables, $paypalParams);
5022            return;
5023        }
5024
5025        // create payment
5026        $savePaymentArr = array(
5027            'user_id' => $user->id ?? null,
5028            'amount' => $totalAmount,
5029            'status' => 1,
5030            'reference_id' => $user->id ?? null,
5031            'payment_transaction_password' => $ptPassword,
5032            'card_company' => $cardCompany,
5033            'param1' => json_encode($paypalParams),
5034            'form_type' => $formType,
5035            'ordd' => $paymentHash,
5036            'transaction_code' => $paymentHash,
5037            'currency_id' => $currencyId,
5038            'currency_code' => $currencyCode,
5039            'payment_id' => $paymentPlanId,
5040            'price_id' => $priceId,
5041            'payment_type' => $paymentType
5042        );
5043
5044        $this->Payment->clear();
5045        $this->Payment->create();
5046        $this->Payment->set($savePaymentArr);
5047        $this->Payment->validate = array();
5048
5049        // update/add user`s settlement amount
5050        $this->User->updateUserPayments($savePaymentArr);
5051
5052        // set payment_id
5053        $paymentSaveID = $this->Payment->id;
5054        $data = array('payment_id' => $paymentSaveID);
5055        $paymentType = Configure::read('payment_types.payment_receivable');
5056
5057        // reservation receivable
5058        if ($reservationReceivableAmount > 0) {
5059            $savePaymentArr = array(
5060                'user_id' => $user->id,
5061                'amount' => $reservationReceivableAmount,
5062                'status' => 1,
5063                'type_id' => 1,
5064                'reference_id' => $user->id,
5065                'card_company' => $cardCompany,
5066                'param1' => json_encode($data),
5067                'form_type' => Configure::read('payment_credit_receivable'),
5068                'ordd' => $paymentHash,
5069                'transaction_code' => $paymentHash,
5070                'currency_id' => $currencyId,
5071                'currency_code' => $currencyCode,
5072                'payment_id' => $paymentPlanId,
5073                'price_id' => $priceId,
5074                'payment_type' => $paymentType
5075            );
5076
5077            // create new payment for reservation receivable
5078            $this->Payment->clear();
5079            $this->Payment->create();
5080            $this->Payment->set($savePaymentArr);
5081            if (!$this->Payment->save()) {
5082                //$this->log(__METHOD__ . ' Failed to save payment data for reservation receivable.' . json_encode($savePaymentArr), $logFileName);
5083                return;
5084            }
5085
5086            // set payment_id
5087            $rrPaymentID = $this->Payment->id;
5088
5089            //update/add user`s settlement amount
5090            $this->User->updateUserPayments($savePaymentArr);
5091
5092            // set payment receivable statuses to 2 - received
5093            $this->PaymentReceivable->updateReceivableReservationPayment(
5094                $user->id,
5095                array(
5096                    'status' => 2,
5097                    'payment_id' => $rrPaymentID,
5098                    'payment_collection_date' => $dateTimeNow,
5099                    'card_company' => $cardCompany,
5100                    'payment_plan_id' => $paymentPlanId,
5101                    'membership_type_index' => $membershipStatusIndex
5102                ),
5103                array(
5104                    'PaymentReceivable.user_id' => $user->id,
5105                    'PaymentReceivable.status' => 0,
5106                    'PaymentReceivable.payment_element_type' => Configure::read('payment_element_type.reservation'),
5107                    'PaymentReceivable.created <=' => $dateTimeNow
5108                )
5109            );
5110        }
5111
5112        // appreciation receivable
5113        if ($appreciationReceivableAmount > 0) {
5114            $savePaymentArr = array(
5115                'user_id' => $user->id,
5116                'amount' => $appreciationReceivableAmount,
5117                'status' => 1,
5118                'type_id' => 1,
5119                'reference_id' => $user->id,
5120                'card_company' => $cardCompany,
5121                'param1' => json_encode($data),
5122                'form_type' => Configure::read('payment_credit_appreciation_receivable'),
5123                'ordd' => $paymentHash,
5124                'transaction_code' => $paymentHash,
5125                'currency_id' => $currencyId,
5126                'currency_code' => $currencyCode,
5127                'payment_id' => $paymentPlanId,
5128                'price_id' => $priceId,
5129                'payment_type' => $paymentType
5130            );
5131
5132            // create new payment for appreciation receivable
5133            $this->Payment->clear();
5134            $this->Payment->create();
5135            $this->Payment->set($savePaymentArr);
5136            if (!$this->Payment->save()) {
5137                $this->log(__METHOD__ . ' Failed to save payment data for appreciation receivable.' . json_encode($savePaymentArr), $logFileName);
5138                return;
5139            }
5140
5141            // set payment_id
5142            $arPaymentID = $this->Payment->id;
5143
5144            //update/add user`s settlement amount
5145            $this->User->updateUserPayments($savePaymentArr);
5146
5147            // set payment receivable statuses to 2 - received
5148            $this->PaymentReceivable->updateReceivableReservationPayment(
5149                $user->id,
5150                array(
5151                    'status' => 2,
5152                    'payment_id' => $arPaymentID,
5153                    'payment_collection_date' => $dateTimeNow,
5154                    'card_company' => $cardCompany,
5155                    'payment_plan_id' => $paymentPlanId,
5156                    'membership_type_index' => $membershipStatusIndex
5157                ),
5158                array(
5159                    'PaymentReceivable.user_id' => $user->id,
5160                    'PaymentReceivable.status' => 0,
5161                    'PaymentReceivable.payment_element_type' => Configure::read('payment_element_type.appreciation'),
5162                    'PaymentReceivable.created <=' => $dateTimeNow
5163                )
5164            );
5165        }
5166
5167        // live receivable
5168        if ($liveReceivableAmount > 0) {
5169            $savePaymentArr = array(
5170                'user_id' => $user->id,
5171                'amount' => $liveReceivableAmount,
5172                'status' => 1,
5173                'type_id' => 1,
5174                'reference_id' => $user->id,
5175                'card_company' => $cardCompany,
5176                'param1' => json_encode($data),
5177                'form_type' => Configure::read('payment_live_lesson_receivable'),
5178                'ordd' => $paymentHash,
5179                'transaction_code' => $paymentHash,
5180                'currency_id' => $currencyId,
5181                'currency_code' => $currencyCode,
5182                'payment_id' => $paymentPlanId,
5183                'price_id' => $priceId,
5184                'payment_type' => $paymentType
5185            );
5186
5187            // create new payment for live receivable
5188            $this->Payment->clear();
5189            $this->Payment->create();
5190            $this->Payment->set($savePaymentArr);
5191            if (!$this->Payment->save()) {
5192                $this->log(__METHOD__ . ' Failed to save payment data for live receivable.' . json_encode($savePaymentArr), $logFileName);
5193                return;
5194            }
5195
5196            // set payment_id
5197            $lrPaymentID = $this->Payment->id;
5198
5199            //update/add user`s settlement amount
5200            $this->User->updateUserPayments($savePaymentArr);
5201
5202            // set payment receivable statuses to 2 - received
5203            $this->PaymentReceivable->updateReceivableReservationPayment(
5204                $user->id,
5205                array(
5206                    'status' => 2,
5207                    'payment_id' => $lrPaymentID,
5208                    'payment_collection_date' => $dateTimeNow,
5209                    'card_company' => $cardCompany,
5210                    'payment_plan_id' => $paymentPlanId,
5211                    'membership_type_index' => $membershipStatusIndex
5212                ),
5213                array(
5214                    'PaymentReceivable.user_id' => $user->id,
5215                    'PaymentReceivable.status' => 0,
5216                    'PaymentReceivable.payment_element_type' => Configure::read('payment_element_type.live'),
5217                    'PaymentReceivable.created <=' => $dateTimeNow
5218                )
5219            );
5220        }
5221
5222        $fields = array('status' => 1);
5223        if (isset($paypalParams)) {
5224            $fields['response_text'] = array('paypal_response' => $paypalParams);
5225        }
5226
5227        // update payment transaction
5228        $this->PaymentTransaction->updateWPPaymentTransaction(array('id' => $ptId ?? null, 'fields' => $fields));
5229        return 'success_order';
5230    }
5231
5232    private function savePaypalFailedSettlement($receivables = array(), $paypalParams = array()) {
5233        if ($receivables && $paypalParams) {
5234            foreach ($receivables as $configKey => $amount) {
5235                if ($amount > 0) {
5236                    $paypalParams['formType'] = Configure::read($configKey);
5237                    $paypalParams['money'] = $amount;
5238                    
5239                    $this->Payment->paypalSaveFailedSettlement($paypalParams);
5240                }
5241            }
5242        }
5243    }
5244
5245    // ~NJ-29078 - Withdraw Aftee Process Payment
5246    private function processParentAfteePayment($params = array())
5247    {
5248        $logFileName = 'family_plan';
5249        if (
5250            !isset($params['user']) ||
5251            !isset($params['paymentTransaction'])
5252        ) {
5253            $this->log('__METHOD__' . ' missing parameter(s). --> ' . json_encode($params), $logFileName);
5254            return false;
5255        }
5256
5257        $user = $params['user'];
5258        $pt = $params['paymentTransaction'];
5259
5260        $ptId = $pt['id'];
5261        $ptPassword = isset($pt['password']) ? $pt['password'] : '';
5262        $ptParams = json_decode($pt['payment_params'], true);
5263
5264        $formType = $ptParams['formType'] ?? null;
5265        $currencyCode = $ptParams['currencyCode'] ?? null;
5266        $paymentPlanId = $ptParams['paymentPlanId'] ?? null;
5267        $priceId = $ptParams['priceId'] ?? null;
5268        $paymentType = $ptParams['paymentType'] ?? null;
5269        $platform = $ptParams['platform'] ?? null;
5270        $paymentHash = $ptParams['orderCode'] ?? null;
5271        $afteeTransactionIdentifier = $ptParams['afteeTransactionIdentifier'] ?? null;
5272
5273        $membershipStatusIndex = UserTable::getStudentMembershipStatus($user->id);
5274        $currencyId = Configure::read('default.settlement_currency_id'); // set currency id to jpy
5275        $cardCompany = Configure::read('card_company.aftee');
5276        $dateTimeNow = date('Y-m-d H:i:s');
5277
5278        $appreciationFlg = 0;
5279        // $this->log(__METHOD__ . ' aftee debug --> ' . json_encode($params), $logFileName);
5280        // $this->log(__METHOD__ . ' aftee debug --> ' . json_encode($pt), $logFileName);
5281        // $this->log(__METHOD__ . ' aftee debug --> ' . $paymentHash, $logFileName);
5282
5283        // initial aftee amount
5284        $totalAmount = (int)($ptParams['paymentAmount'] ?? 0);
5285
5286        if ($totalAmount > 0) {
5287            if (isset($user->aftee_transaction_identifier) && !empty($user->aftee_transaction_identifier)) {
5288                $related_id = $user->aftee_transaction_identifier;
5289            } else {
5290                $related_id = $afteeTransactionIdentifier;
5291            }
5292
5293            // load PayPal class
5294            if (!class_exists('AfteePaymentService')) {
5295                App::import('Lib', 'AfteePaymentService');
5296            }
5297
5298            $afteeChecksumData = array(
5299                'shopItemId' => "AFTEE" . $formType,
5300                'itemName' => 'FamilyPlanRegistration',
5301                'itemPrice' => $totalAmount,
5302                'itemCount' => 1,
5303                'customerPhoneNumber' => $user->phone_number,
5304                'customerEmail' => $user->email,
5305                'shopTransactionNo' => $paymentHash,
5306                'userID' => $user->id
5307            );
5308            $afteeService = new AfteePaymentService();
5309            $checksum = $afteeService->generateChecksum($afteeChecksumData, false);
5310
5311
5312            $afteeData = array(
5313                'authentication_token' => $user->card_token,
5314                'related_id' => $related_id,
5315                'checksum' => $checksum['checksum'],
5316                'shop_transaction_no' => $paymentHash,
5317                'transaction_options' => array(1)
5318            );
5319
5320            $afteePaymentData = array_merge($afteeData, $checksum['settlementData']);
5321
5322            // process Aftee direct payment
5323            $res = $afteeService->directPayment($afteePaymentData);
5324            $checkRes = json_decode($res, true);
5325            //$this->log(__METHOD__ . ' aftee --> ' . json_encode($afteePaymentData) . ' --> ' . json_encode($checkRes), $logFileName);
5326
5327            if (isset($checkRes['object']) && $checkRes['object'] == 'transaction') {
5328                $paymentSuccess = true;
5329            } else if (!array_key_exists("object", $checkRes) || (isset($checkRes['object']) && $checkRes['object'] == 'error')) {
5330                $paymentSuccess = false;
5331            }
5332        } else {
5333            // zero payment
5334            $checkRes = array('aftee zero payment --> family plan registration');
5335            $paymentSuccess = true;
5336        }
5337
5338        if (!$paymentSuccess) {
5339            $this->log(__METHOD__ . ' aftee error --> ' . json_encode($checkRes) . ' --> ' . json_encode($params), $logFileName);
5340            return;
5341        }
5342
5343        // payment history data amount
5344        $reservationReceivableAmount = isset($ptParams['reservationReceivableAmount']) ? $ptParams['reservationReceivableAmount'] : 0;
5345        $appreciationReceivableAmount = isset($ptParams['appreciationReceivableAmount']) ? $ptParams['appreciationReceivableAmount'] : 0;
5346        $liveReceivableAmount = isset($ptParams['liveReceivableAmount']) ? $ptParams['liveReceivableAmount'] : 0;
5347
5348        // create payment
5349        $savePaymentArr = array(
5350            'user_id' => $user->id,
5351            'status' => 1,
5352            'reference_id' => $user->id,
5353            'payment_transaction_password' => $ptPassword,
5354            'card_company' => $cardCompany,
5355            'param1' => json_encode($checkRes),
5356            'form_type' => $formType,
5357            'ordd' => $paymentHash,
5358            'transaction_code' => $paymentHash,
5359            'currency_id' => $currencyId,
5360            'currency_code' => $currencyCode,
5361            'payment_id' => $paymentPlanId,
5362            'price_id' => $priceId,
5363            'payment_type' => $paymentType
5364        );
5365
5366        $this->Payment->clear();
5367        $this->Payment->create();
5368        $this->Payment->set($savePaymentArr);
5369        $this->Payment->validate = array();
5370
5371        // update/add user`s settlement amount
5372        $this->User->updateUserPayments($savePaymentArr);
5373
5374        // set payment_id
5375        $paymentSaveID = $this->Payment->id;
5376        $data = array('payment_id' => $paymentSaveID);
5377        $paymentType = Configure::read('payment_types.payment_receivable');
5378
5379        // reservation receivable
5380        if ($reservationReceivableAmount > 0) {
5381            $savePaymentArr = array(
5382                'user_id' => $user->id,
5383                'amount' => $reservationReceivableAmount,
5384                'status' => 1,
5385                'type_id' => 1,
5386                'reference_id' => $user->id,
5387                'card_company' => $cardCompany,
5388                'param1' => json_encode($data),
5389                'form_type' => Configure::read('payment_credit_receivable'),
5390                'ordd' => $paymentHash,
5391                'transaction_code' => $paymentHash,
5392                'currency_id' => $currencyId,
5393                'currency_code' => $currencyCode,
5394                'payment_id' => $paymentPlanId,
5395                'price_id' => $priceId,
5396                'payment_type' => $paymentType
5397            );
5398
5399            // create new payment for reservation receivable
5400            $this->Payment->clear();
5401            $this->Payment->create();
5402            $this->Payment->set($savePaymentArr);
5403            if (!$this->Payment->save()) {
5404                $this->log(__METHOD__ . ' Failed to save payment data for reservation receivable.' . json_encode($savePaymentArr), $logFileName);
5405                return;
5406            }
5407
5408            // set payment_id
5409            $rrPaymentID = $this->Payment->id;
5410
5411            //update/add user`s settlement amount
5412            $this->User->updateUserPayments($savePaymentArr);
5413
5414            // set payment receivable statuses to 2 - received
5415            $this->PaymentReceivable->updateReceivableReservationPayment(
5416                $user->id,
5417                array(
5418                    'status' => 2,
5419                    'payment_id' => $rrPaymentID,
5420                    'payment_collection_date' => $dateTimeNow,
5421                    'card_company' => $cardCompany,
5422                    'payment_plan_id' => $paymentPlanId,
5423                    'membership_type_index' => $membershipStatusIndex
5424                ),
5425                array(
5426                    'PaymentReceivable.user_id' => $user->id,
5427                    'PaymentReceivable.status' => 0,
5428                    'PaymentReceivable.payment_element_type' => Configure::read('payment_element_type.reservation'),
5429                    'PaymentReceivable.created <=' => $dateTimeNow
5430                )
5431            );
5432        }
5433
5434        // appreciation receivable
5435        if ($appreciationReceivableAmount > 0) {
5436            $savePaymentArr = array(
5437                'user_id' => $user->id,
5438                'amount' => $appreciationReceivableAmount,
5439                'status' => 1,
5440                'type_id' => 1,
5441                'reference_id' => $user->id,
5442                'card_company' => $cardCompany,
5443                'param1' => json_encode($data),
5444                'form_type' => Configure::read('payment_credit_appreciation_receivable'),
5445                'ordd' => $paymentHash,
5446                'transaction_code' => $paymentHash,
5447                'currency_id' => $currencyId,
5448                'currency_code' => $currencyCode,
5449                'payment_id' => $paymentPlanId,
5450                'price_id' => $priceId,
5451                'payment_type' => $paymentType
5452            );
5453
5454            // create new payment for appreciation receivable
5455            $this->Payment->clear();
5456            $this->Payment->create();
5457            $this->Payment->set($savePaymentArr);
5458            if (!$this->Payment->save()) {
5459                $this->log(__METHOD__ . ' Failed to save payment data for appreciation receivable.' . json_encode($savePaymentArr), $logFileName);
5460                return;
5461            }
5462
5463            // set payment_id
5464            $arPaymentID = $this->Payment->id;
5465
5466            //update/add user`s settlement amount
5467            $this->User->updateUserPayments($savePaymentArr);
5468
5469            // set payment receivable statuses to 2 - received
5470            $this->PaymentReceivable->updateReceivableReservationPayment(
5471                $user->id,
5472                array(
5473                    'status' => 2,
5474                    'payment_id' => $arPaymentID,
5475                    'payment_collection_date' => $dateTimeNow,
5476                    'card_company' => $cardCompany,
5477                    'payment_plan_id' => $paymentPlanId,
5478                    'membership_type_index' => $membershipStatusIndex
5479                ),
5480                array(
5481                    'PaymentReceivable.user_id' => $user->id,
5482                    'PaymentReceivable.status' => 0,
5483                    'PaymentReceivable.payment_element_type' => Configure::read('payment_element_type.appreciation'),
5484                    'PaymentReceivable.created <=' => $dateTimeNow
5485                )
5486            );
5487        }
5488
5489        // live receivable
5490        if ($liveReceivableAmount > 0) {
5491            $savePaymentArr = array(
5492                'user_id' => $user->id,
5493                'amount' => $liveReceivableAmount,
5494                'status' => 1,
5495                'type_id' => 1,
5496                'reference_id' => $user->id,
5497                'card_company' => $cardCompany,
5498                'param1' => json_encode($data),
5499                'form_type' => Configure::read('payment_live_lesson_receivable'),
5500                'ordd' => $paymentHash,
5501                'transaction_code' => $paymentHash,
5502                'currency_id' => $currencyId,
5503                'currency_code' => $currencyCode,
5504                'payment_id' => $paymentPlanId,
5505                'price_id' => $priceId,
5506                'payment_type' => $paymentType
5507            );
5508
5509            // create new payment for live receivable
5510            $this->Payment->clear();
5511            $this->Payment->create();
5512            $this->Payment->set($savePaymentArr);
5513            if (!$this->Payment->save()) {
5514                $this->log(__METHOD__ . ' Failed to save payment data for live receivable.' . json_encode($savePaymentArr), $logFileName);
5515                return;
5516            }
5517
5518            // set payment_id
5519            $lrPaymentID = $this->Payment->id;
5520
5521            //update/add user`s settlement amount
5522            $this->User->updateUserPayments($savePaymentArr);
5523
5524            // set payment receivable statuses to 2 - received
5525            $this->PaymentReceivable->updateReceivableReservationPayment(
5526                $user->id,
5527                array(
5528                    'status' => 2,
5529                    'payment_id' => $lrPaymentID,
5530                    'payment_collection_date' => $dateTimeNow,
5531                    'card_company' => $cardCompany,
5532                    'payment_plan_id' => $paymentPlanId,
5533                    'membership_type_index' => $membershipStatusIndex
5534                ),
5535                array(
5536                    'PaymentReceivable.user_id' => $user->id,
5537                    'PaymentReceivable.status' => 0,
5538                    'PaymentReceivable.payment_element_type' => Configure::read('payment_element_type.live'),
5539                    'PaymentReceivable.created <=' => $dateTimeNow
5540                )
5541            );
5542        }
5543
5544        $fields = array('status' => 1);
5545        if (isset($checkRes)) {
5546            $fields['response_text'] = array('aftee' => $checkRes);
5547        }
5548
5549        // update payment transaction
5550        $this->PaymentTransaction->updateWPPaymentTransaction(array('id' => $ptId, 'fields' => $fields));
5551
5552        return 'success_order';
5553    }
5554
5555    protected function checkCompanyIPForSMS($userId) {
5556        $userIp = $_SERVER['REMOTE_ADDR'];
5557        
5558        $this->InhouseIp->openDBReplica();
5559
5560        $checkCompanyIp = $this->InhouseIp->find('first', array(
5561            'conditions' => array(
5562                'ip_address' => $userIp,
5563                'status' => 1
5564            ),
5565        ));
5566
5567        $this->InhouseIp->closeDBReplica();
5568    
5569        if (!empty($checkCompanyIp)) {
5570            $sms_through_flg = array('sms_through_flg' => 1);
5571            $this->User->updateUserById(array('userData' => $sms_through_flg, 'id' => $userId));
5572            return true;
5573        }
5574
5575        return false;
5576    }
5577
5578    protected function setPerMonthSymbol($language = null, $addDivider = false) {
5579        $allowedLanguages = Configure::read('allowed_currencies');
5580
5581        $perMonthSymbol =  __dx('register', 'month', '月');
5582        $dividerCurrencyCode = Configure::read('currency_jpy');
5583        if (in_array($language, $allowedLanguages) && $language == Configure::read('language_ptbr')) {
5584            $dividerCurrencyCode = Configure::read('currency_brl');
5585            $perMonthSymbol =  __d('register', '毎月');
5586        }
5587
5588        if ($addDivider) {
5589            $perMonthSymbol = myTools::getPriceMonthlyDivider($dividerCurrencyCode) . $perMonthSymbol;
5590        }
5591
5592        $this->set('perMonthSymbol', $perMonthSymbol);
5593    }
5594
5595    public function corporateIpRestrictionLogout()
5596    {
5597        $this->Auth->flash(__d("login", "このアカウントは指定された場所でのみ利用可能です"));
5598        $this->Auth->logout();
5599        return $this->redirect(myTools::getUrl() . '/login');
5600    }
5601
5602}